编组C ++指针接口通过C#函数调用非默认AppDomain

我在C ++和C#代码之间有一个有效的CLI接口。 代码有一个C ++抽象接口,如:

-------------C++ Interface--------------- namespace cppns { class cppInterface { public: virtual bool Start(const char *pcDir) = 0; }; } ------Implementation of abstract C++ interface in same dll--------- namespace cppns { class cppimp : public cppInterface private: gcroot mInternalClassAccess; public: cppimp::cppimp() { mInternalClassAccess = gcnew MyInternalCSharpClass(); } virtual bool cppimp::Start(const char *pcDir) { System::AppDomain ^appDom = AppDomain::CurrentDomain::get(); System::String ^strDomainName = appDom->FriendlyName; mInternalClassAccess->Initalize(pcDir); } } ---------Method to create an instance of the class in a factory-------------- cppns::cppInterface *GetImplObject() { return new cppns::cppimp(); } ----------Factory class .h to allow C++ to get an instance of the cppimp class------ ------The C++ code knows about the abstract interface by including the header file-- ------FactoryExport is __declspec(dllexport) when compiled in dll and--------------- ----- __declspec(dllimport) when used as a header file in exe that uses header------ class FactoryExport ClassFactory { public: static cppns::cppInterface *CreateImpl(); }; ----------Factory class .cpp to allow C++ to get an instance of the cppimp class------ cppns::cppInterface *ClassFactory::CreateImpl() { return GetImplObject(); } 

这段代码正确地允许我调用CreateImpl来获得包含Start方法的接口的实现。 我的问题是我试图强制整个CLR / .NET加载并执行一个不是默认AppDomain的AppDomain。 我可以使用以下代码创建辅助AppDomain:

  CComPtr pRuntimeHost; //Retrieve a pointer to the ICorRuntimeHost interface HRESULT hr = CorBindToRuntimeEx( L"v2.0.50727", //Retrieve last version before 4.0. // NULL, //Retrieve latest version by default L"wks", STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN | STARTUP_CONCURRENT_GC, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, (void**)&pRuntimeHost.p ); hr = pRuntimeHost->Start(); DWORD dwAppDomainId = 22; WCHAR domainName[80 + 1]; swprintf(domainName, 80, L"%s-%ld",L"NoDefaultDomain", dwAppDomainId); CComPtr pUnknownAppDomain; hr = pRuntimeHost->CreateDomainEx(domainName, NULL, NULL, &pUnknownAppDomain); CComPtr pAppDomain; hr = pUnknownAppDomain->QueryInterface(__uuidof(_AppDomain), (VOID**)&pAppDomain.p); BSTR bstrFriendlyName; hr = pAppDomain->get_FriendlyName(&bstrFriendlyName); if (SUCCEEDED(hr)) { _bstr_t bstrFriendlyNameWrap(bstrFriendlyName, false); } _bstr_t bstrAssemblyName("InteropCode"); CComPtr pAssembly; hr = pAppDomain->Load_2(bstrAssemblyName, &pAssembly); BSTR bstrFullName; hr = pAssembly->get_FullName(&bstrFullName); if (SUCCEEDED(hr)) { _bstr_t bstrFullNameWrap(bstrFullName, false); std::cout << "Assembly name is: " << bstrFullNameWrap << "\n"; } 

每次尝试让工厂向我返回此辅助应用程序域中cppns :: cppInterface的接口都失败了。 我甚至试图创建一个二级工厂,它是一个C#类,它返回指向已实现接口的指针,以便对程序集上的Invoke调用有希望导致其余的代码在我加载程序集的AppDomain中执行但是Invoke返回一个IDispatch指针,我似乎无法映射回我的接口上的任何类型的C ++指针。

 namespace cppns { public ref class NetFactory { public: NetFactory() { } cppInterface *CreateInterop() { return GetImplObject();; } }; } 

是否有另一种方法可以让所有内容在辅助AppDomain中运行,或者是否可以在调用Start方法时使用IDispatch指针?

我已经设法让大多数.NET内容在另一个域中运行。 似乎没有办法让CLI层在默认AppDomain以外的任何其他地方运行。

为了完成这项工作,我需要让位于两个appdomains中的类派生自MarshalByRefObject。 在上面的例子中,这意味着我必须更改MyInternalCSharpClass,以便它从MarshalByRefObject派生。 从MyInternalCSharpClass发送和返回的对象也是从MarshalByRefObject派生的,这也是必要的。 最后,我传递和返回的这些相同对象必须具有[Serializable]属性,并且还将所有私有变量标记为public。 请注意,如果通过AppDomains传输的类已经使用Serializable属性,则可以在每个正式的私有变量上使用[XmlIgnore],以避免更改正在执行的序列化。

既然可以在AppDomains之间移动所有内容,我通过执行以下操作创建了第二个AppDomain:

 bool CreateInstanceInAppDomain(const char *pcAppDomainName) { bool bRtn = false; gcroot csStrAppDomainName (gcnew String(pcAppDomainName)); mAppDomain = AppDomain::CreateDomain(csStrAppDomainName); delete csStrAppDomainName; Object^ MyInternalObject = mAppDomain->CreateInstanceAndUnwrap("AssemblyName", "ClassNameSpace.MyInternalCSharpClass"); mInternalClassAccess = dynamic_cast(MyInternalObject); if (mInternalClassAccess) { bRtn = true; } return bRtn; }