PDA

View Full Version : کار با کلاس های دات نت در C++



hakan648
شنبه 04 مرداد 1393, 16:27 عصر
روش کار با کلاس های .net در C++ ( مدیریت نشده - Native ) به چه صورت است؟ ( بدون استفاده از COM و تنها توسط C++ )

فرض کنید از کلاسی در .net، در C# نمونه سازی کردیم و میخواهیم مقداری از آن کلاس را در C++ بخوانیم.

روشی که من امتحان کردم، ارسال پوینتری از نوع Type از کلاس Label به C++ و استفاده از آن در CLR لود شده بود.

کدهای زیر حاصل روش فوق است که با خطای System.AccessViolationException متوقف می شود.

C#
static void Main(string[] args)
{
var label = new Label { Text = "Some Text" };

//Send Type because CLR Invocation is defined on object's Type
var labelType = label.GetType();

GCHandle gch = GCHandle.Alloc(labelType);

IntPtr labelTypeIntPtr = GCHandle.ToIntPtr(gch);

ReadDotNetClass(labelTypeIntPtr);
}

//native function definition
[DllImport("Unmanaged.dll")]
private static extern void ReadDotNetClass(IntPtr labelTypeIntPtr);


C++
extern "C" __declspec(dllexport) void ReadDotNetClass(_TypePtr labelTypePtr)
{
PCWSTR pszVersion = L"v4.0.30319";
PCWSTR pszAssemblyName= L"System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
PCWSTR pszClassName=L"System.Web.UI.WebControls.Label";

ICLRMetaHost *pMetaHost = NULL;
ICLRRuntimeInfo *pRuntimeInfo = NULL;
ICorRuntimeHost *pCorRuntimeHost = NULL;
IUnknownPtr spAppDomainThunk = NULL;
_AppDomainPtr spDefaultAppDomain = NULL;

// The .NET assembly to load.
bstr_t bstrAssemblyName(pszAssemblyName);
_AssemblyPtr spAssembly = NULL;

// The .NET class to instantiate.
bstr_t bstrClassName(pszClassName);
variant_t vtObject;

// The instance method in the .NET class to invoke.
bstr_t bstrMethodName(L"Text");
SAFEARRAY *psaMethodArgs = NULL;
variant_t vtStringRet;

CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
pMetaHost->GetRuntime(pszVersion, IID_PPV_ARGS(&pRuntimeInfo));

BOOL fLoadable;
pRuntimeInfo->IsLoadable(&fLoadable);
pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_PPV_ARGS(&pCorRuntimeHost));
pCorRuntimeHost->Start();
pCorRuntimeHost->GetDefaultDomain(&spAppDomainThunk);
spAppDomainThunk->QueryInterface(IID_PPV_ARGS(&spDefaultAppDomain));
spDefaultAppDomain->Load_2(bstrAssemblyName, &spAssembly);
psaMethodArgs = SafeArrayCreateVector(VT_VARIANT, 0, 0);

// Invoke method from the Type interface.
HRESULT hr = labelTypePtr->InvokeMember_3(bstrMethodName, static_cast<BindingFlags>(
BindingFlags_Instance | BindingFlags_Public | BindingFlags_GetProperty),
NULL, vtObject, psaMethodArgs, &vtStringRet);
if (FAILED(hr))
wprintf(L"Failed to invoke Method w/hr 0x%08lx\n", hr);
}


در صورتی که روشی برای انجام این کار سراغ دارید، در اختیار بنده قرار دهید.

با تشکر