I want to pass a .net class to a native function and work with that class (i.e. get the value of a Property). Note that i don't want to use C++/CLI.
For example, i have a Label in my web application and i want to get Text property in my native C++ code.
My Attempt
I tried to load CLR in C++ and read Text property of a label which is instantiated in C#, but i encountered System.AccessViolationException exception.
Here is my code:
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. //System.AccessViolationException occurred here 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); } The C++ code is simplified version of this code sample from microsoft.
Please note that i just need to deal with .net classes (not my own classes) in native C++, and i don't want to use COM or other methods that take place out side of native world.