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

时间:2011-12-06 20:29:45

标签: c# c++ unmanaged managed

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

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

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

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

根据Internet上的代码,主机.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;
}

2 个答案:

答案 0 :(得分:5)

是的,我同意约翰的观点。您真的不想创建运行时的新实例并明确地托管它。首先,这背后的管道没有很好的记录,可能会在未来的版本中发生变化。其次,C ++ / CLI旨在以最有效和最安全的方式完成此任务。

  1. 编写代表所需.Net功能的本机C ++接口。

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

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

答案 1 :(得分:3)

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

确实不希望将COM添加到组合中。这将使事情变得更加缓慢。

另外,这些“性能原因”是否可以避免托​​管代码实际量化?这听起来有点像一个轶事,以避免他们不想要的东西。此外,您可以指出他们已经使用托管代码,因为C#是混合使用。