gpt4 book ai didi

c# - 通过非默认 AppDomain 中的 C# 函数调用编码 C++ 指针接口(interface)

转载 作者:行者123 更新时间:2023-11-30 18:00:13 25 4
gpt4 key购买 nike

我在 C++ 和 C# 代码之间有一个可用的 CLI 接口(interface)。该代码有一个 C++ 抽象接口(interface),如:

-------------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<MyInternalCSharpClass^> 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 方法的接口(interface)的实现。我的问题是我试图强制整个 CLR/.NET 加载并执行到一个不是默认 AppDomain 的 AppDomain 中。我可以使用以下代码创建辅助 AppDomain:

   CComPtr<ICorRuntimeHost> 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<IUnknown> pUnknownAppDomain;
hr = pRuntimeHost->CreateDomainEx(domainName, NULL, NULL, &pUnknownAppDomain);

CComPtr<_AppDomain> 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<_Assembly> 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 的接口(interface)都失败了。我什至尝试创建一个辅助工厂,它是一个 C# 类,它返回指向已实现接口(interface)的指针,以便对 Assembly 的 Invoke 调用有望导致其余代码在我将 Assembly 加载到的 AppDomain 中执行,但是Invoke 返回一个 IDispatch 指针,我似乎无法将其映射回我的界面上的任何类型的 C++ 指针。

namespace cppns
{
public ref class NetFactory
{
public:
NetFactory()
{
}

cppInterface *CreateInterop()
{
return GetImplObject();;
}
};
}

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

最佳答案

我已经设法让大部分 .NET 东西在另一个域中运行。似乎没有办法让 CLI 层在默认 AppDomain 以外的任何地方运行。

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

既然一切都可以在 AppDomain 之间移动,我通过执行以下操作创建了第二个 AppDomain:

bool CreateInstanceInAppDomain(const char *pcAppDomainName)
{
bool bRtn = false;

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

return bRtn;
}

关于c# - 通过非默认 AppDomain 中的 C# 函数调用编码 C++ 指针接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10301727/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com