从非托管代码调用托管.NET代码的最佳方式

本文关键字:代码 最佳 方式 NET 非托管代码 调用 | 更新日期: 2023-09-27 18:17:02

我正试图从非托管C++代码中找到调用托管.NET代码的最佳方法。我在我的C++应用程序中找到了关于Hosting.NET的信息,我可以创建一个pRuntimeHost并毫无问题地启动它。

ExecuteInDefaultAppDomain似乎非常有限,因为我真的想给它发送一些参数,并让它返回一个信息结构。最明显的替代方案是使用COM方法,但当前的C#代码并没有真正设置为与方法的接口。

无论哪种方式,我都希望返回整数、字符串(char*(s、双精度和其他核心C++类型。双方都有太多的代码无法将C++转换为C#,使用托管C++是不可接受的解决方案,因为使用此C++代码的其他组出于性能原因不想开始使用托管代码。

目标是尽可能少地修改现有的C++和C#代码,但仍然在C++中的特定点使用C#代码中的方法,而不会严重影响C++代码的速度。

根据在互联网上找到的代码,主机.NET的启动和关闭顺序是:

#include "stdafx.h"
#include <metahost.h>
#pragma comment(lib, "mscoree.lib")
int _tmain(int argc, _TCHAR* argv[])
{
    ICLRMetaHost       *pMetaHost       = NULL;
    ICLRMetaHostPolicy *pMetaHostPolicy = NULL;
    ICLRDebugging      *pCLRDebugging   = NULL;
    HRESULT hr;
    hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost);
    hr = CLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, (LPVOID*)&pMetaHostPolicy);
    hr = CLRCreateInstance(CLSID_CLRDebugging, IID_ICLRDebugging, (LPVOID*)&pCLRDebugging);
    DWORD dwVersion = 0;
    DWORD dwImageVersion = 0;
    ICLRRuntimeInfo *pRuntimeInfo;
    hr = pMetaHost->GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID *)&pRuntimeInfo);
    ICLRRuntimeHost * pRuntimeHost = NULL;
    hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID *)&pRuntimeHost);
    hr = pRuntimeHost->Start();
    DWORD dwRetCode = 0;
    //hr = pRuntimeHost->ExecuteInDefaultAppDomain(argv[1], L"MyNamespace.MyClass", L"Message", L"Hello World!", &dwRetCode);
    // Stop the CLR runtime and shutdown cleanly.
    hr = pRuntimeHost->Stop();
    hr = pRuntimeHost->Release();
    hr = pRuntimeInfo->Release();
    hr = pCLRDebugging->Release();
    hr = pMetaHostPolicy->Release();
    hr = pMetaHost->Release();
    return 0;
}

从非托管代码调用托管.NET代码的最佳方式

是的,我同意约翰的观点。您并不真的想创建一个新的运行时实例并明确地承载它。首先,这背后的管道没有很好的记录,可能会在未来的版本中发生变化。其次,C++/CLI被设计为以最高效、最安全的方式做到这一点。
  1. 编写表示所需.Net功能性的本机C++接口。

  2. 设置一个具有CLR支持的dll,该dll使用umanaged类实现本机接口。在它们的实现内部,您可以创建和访问CLR类型,并将实例变量存储在gcroot<T>字段中。使用clr互操作功能可以在托管/非托管代码、google或bing for marshal_as之间来回封送。

  3. 提供一个(非托管(工厂函数,该函数将创建此组件的实例。此+非托管c++接口是本机代码将看到的API。使用dll的方式与使用非托管dll的方式完全相同。

如果可以接受,最好的解决方案可能是创建一个介于两者之间的托管C++dll。托管C++代码是桥接托管代码和非托管代码的最佳/最有效的方法。

您真的不想在组合中添加COM。这会让事情变得更慢。

此外,这些避免托管代码的"性能原因"实际上是量化的吗?这听起来有点像是为了避免他们不想要的东西而抛出的轶事。此外,您可以指出,它们已经使用托管代码了,因为C#也在其中。