最佳调用从非托管代码托管.NET代码的方式 [英] Best way to call Managed .NET code from Unmanaged code

查看:442
本文介绍了最佳调用从非托管代码托管.NET代码的方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找到调用到从非托管C ++代码托管.NET代码的最佳执行方法。我发现我的C ++应用程序中托管.NET的信息,我能创造一个pRuntimeHost并启动它没有问题。



ExecuteInDefaultAppDomain,因为我似乎很有限真的要送它几个参数,并使其返回的信息的结构。最明显的替代方案是使用COM方法,但目前的C#代码是不是真的设置与方法的接口。



无论哪种方式,我想回到整数,字符串(CHAR *)S,双打等核心C ++类型。目前双方太多的代码到C ++转换为C#和使用托管C ++不是一个可接受的解决方案,因为使用此C ++代码的其他团体不希望开始使用托管代码性能方面的原因。



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



根据互联网的启动和关机顺序来承载.NET上找到的代码是:

 的#includestdafx.h中
&#包括LT; metahost.h>

的#pragma评论(LIB,mscoree.lib)

INT _tmain(INT ARGC,_TCHAR *的argv [])
{
ICLRMetaHost * pMetaHost = NULL;
ICLRMetaHostPolicy * pMetaHostPolicy = NULL;
ICLRDebugging * pCLRDebugging = NULL;

HRESULT小时;
小时= CLRCreateInstance(CLSID_CLRMetaHost,IID_ICLRMetaHost,(LPVOID *)及pMetaHost);
小时= CLRCreateInstance(CLSID_CLRMetaHostPolicy,IID_ICLRMetaHostPolicy,(LPVOID *)及pMetaHostPolicy);
小时= CLRCreateInstance(CLSID_CLRDebugging,IID_ICLRDebugging,(LPVOID *)及pCLRDebugging);

DWORD dwVersion = 0;
DWORD dwImageVersion = 0;
ICLRRuntimeInfo * pRuntimeInfo;
小时= pMetaHost-> GetRuntime(Lv4.0.30319,IID_ICLRRuntimeInfo,(LPVOID *)及pRuntimeInfo);

ICLRRuntimeHost * pRuntimeHost = NULL;
小时= pRuntimeInfo-> GetInterface(CLSID_CLRRuntimeHost,IID_ICLRRuntimeHost,(LPVOID *)及pRuntimeHost);

HR = pRuntimeHost->启动();

DWORD dwRetCode = 0;
//小时= pRuntimeHost-> ExecuteInDefaultAppDomain(的argv [1],LMyNamespace.MyClass,长度消息中,L的Hello World!,&放大器; dwRetCode);

//停止CLR运行时间和关机干净。
HR = pRuntimeHost->停止();
HR = pRuntimeHost->发行();
HR = pRuntimeInfo->发行();
HR = pCLRDebugging->发行();
HR = pMetaHostPolicy->发行();
HR = pMetaHost->发行();

返回0;
}


解决方案

是的,我同意约翰。你真的不希望创建运行时的一个新实例,并明确地主持它。首先,这背后的管道是没有很好的记载,并可能在未来的版本中改变。其次,C ++ / CLI旨在做的正是这一点最有效,最安全的方式。




  1. 编写本地C ++接口,它代表必要的.NET的funcionality。


  2. 设置了CLR支持使用umanaged类,它实现了原生接口的DLL。其内部实现,您可以创建和访问CLR类型,并在 gcroot<存储实例变量; T> 字段。使用CLR互操作的funcionality元帅来回托管/非托管代码之间,谷歌或冰的 marshal_as


  3. 提供一个(非托管)工厂函数,它创建该组件的一个实例。这+非托管C ++接口是你的原生代码会看到API。使用DLL完全相同的方式你会使用非托管的DLL。



I'm trying to find the best performing method of calling into Managed .NET code from Unmanaged C++ code. I have found information on Hosting .NET within my C++ application and I'm able to create a pRuntimeHost and start it without a problem.

The ExecuteInDefaultAppDomain seems very limited since I really want to send it a few parameters and have it return a structure of information. The most obvious alternative is to use COM methods but the current C# code isn't really setup as interfaces with methods.

Either way I want to return integers, strings (char *)s, doubles and other core C++ types. There is too much code on both sides to convert the C++ to C# and using Managed C++ isn't an acceptable solution, since the other groups using this C++ code don't want to start using Managed code for performance reasons.

The goal is modify the existing C++ and C# code as little as possible but still use methods within the C# code at specific points within the C++ without majorly affecting the speed of the C++ code.

Based on code found on the Internet the startup and shutdown sequence to host .NET is:

#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;
}

解决方案

Yes, I agree with John. You don't really want to create a new instance of the runtime and host it explicitely. First, the plumbing behind this is not well documented and could change in future versions. Second, C++/CLI was designed to do exactly this in most efficient and safe way.

  1. Write native C++ interfaces which represents the required .Net funcionality.

  2. Set up a dll with CLR support which implements the native interfaces using umanaged classes. Inside of their implementation you can create and access CLR types and store instance variables in gcroot<T> fields. Use the clr interop funcionality to marshal back and forth between managed/unmanaged code, google or bing for marshal_as.

  3. Provide an (unmanaged) factory function, which creates an instance of this component. This + the unmanaged c++ interface is the API your native code will see. Use the dll exactly the same way you'd use an unmanaged dll.

这篇关于最佳调用从非托管代码托管.NET代码的方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆