C# 从非托管代码调用托管.NET代码的最佳方法 我试图找到从非托管C++代码中调用托管.NET代码的最佳执行方法。我在我的C++应用程序中找到了关于托管.NET的信息,我能够创建一个PrutMeMeST并启动它而没有问题。

C# 从非托管代码调用托管.NET代码的最佳方法 我试图找到从非托管C++代码中调用托管.NET代码的最佳执行方法。我在我的C++应用程序中找到了关于托管.NET的信息,我能够创建一个PrutMeMeST并启动它而没有问题。,c#,c++,unmanaged,managed,C#,C++,Unmanaged,Managed,ExecuteInDefaultAppDomain似乎非常有限,因为我确实希望向它发送一些参数,并让它返回信息结构。最明显的替代方法是使用COM方法,但当前的C#代码并没有真正设置为与方法的接口 我想返回整数、字符串(char)、双倍和其他核心C++类型。在C++中,有太多代码将C++转换成C语言,使用托管C++不是一个可接受的解决方案,因为使用C++代码的其他组不想开始使用托管代码,原因是性能方面的原因。 目标是尽可能少地修改现有的C++和C代码,但仍然使用C++代码中的特定点内的方法,而不影

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;
}
#包括“stdafx.h”
#包括
#pragma注释(lib,“mscoree.lib”)
int _tmain(int argc,_TCHAR*argv[]
{
ICLRMetaHost*pMetaHost=NULL;
ICLRMetaHostPolicy*pMetaHostPolicy=NULL;
ICLRDebugging*pCLRDebugging=NULL;
HRESULT-hr;
hr=CLRCreateInstance(CLSID\u CLRMETHOST、IID\u ICLRMetaHost(LPVOID*)和PMETHOST);
hr=CLRCreateInstance(CLSID_CLRMetaHostPolicy,IID_ICLRMetaHostPolicy,(LPVOID*)和pMetaHostPolicy);
hr=CLRCreateInstance(CLSID_CLRDebuging,IID_ICLRDebug,(LPVOID*)和PCLRDebug);
DWORD dwVersion=0;
DWORD dwImageVersion=0;
ICLRRuntimeInfo*pRuntimeInfo;
hr=pMetaHost->GetRuntime(L“v4.0.30319”,IID_iclruntimeinfo,(LPVOID*)和pRuntimeInfo);
ICLRRuntimeHost*pRuntimeHost=NULL;
hr=pRuntimeInfo->GetInterface(CLSID\u CLRRuntimeHost,IID\u ICLRRuntimeHost,(LPVOID*)和pRuntimeHost);
hr=pRuntimeHost->Start();
DWORD dwRetCode=0;
//hr=pRuntimeHost->ExecuteInDefaultAppDomain(argv[1],L“MyNamespace.MyClass”,L“Message”,L“Hello World!”,&dwRetCode);
//停止CLR运行时并干净地关闭。
hr=pRuntimeHost->Stop();
hr=pRuntimeHost->Release();
hr=pRuntimeInfo->Release();
hr=pclrdebug->Release();
hr=pMetaHostPolicy->Release();
hr=pMetaHost->Release();
返回0;
}

<代码> > p>如果它是可接受的,最好的解决办法可能是创建一个托管的C++ DLL。托管C++代码是桥接托管和非托管代码的最好/最有效的方式。 你真的不想在混音中加入COM。这将使事情更慢


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

是的,我同意John的观点。您并不是真的想创建一个新的运行时实例并明确地托管它。首先,这背后的管道没有很好的文档记录,在未来的版本中可能会发生变化。其次,C++/CLI的设计正是为了以最高效、最安全的方式实现这一点

< p>编写表示所需.NET函数的本地C++接口。

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

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


  • 创建一个附加AppDe域的原因是C++代码已经使用了一些特定的默认AppDeMand,我不想让我的.NET组件干扰当前代码,也避免让他们的东西干扰我的。顺便说一句,我成功地使CLI层工作得很好,但我仍在试图找出如何将整个CLI层放入一个单独的AppDomain中,该AppDomain不是默认的AppDomain。我自己还没有尝试过这样做,但理论上这不应该是个问题。我理解您的场景是从本机组件调用托管组件,对吗?有一种称为“线程升级”(google或bing)的功能,每当本机线程首次尝试执行托管代码时,它都会将本机线程升级为托管线程。因为CLR不知道以这种方式调用的托管代码应该在哪个AppDomain中执行,所以它将其放入默认的AppDomain中。因此,您必须显式地处理该转换,可能需要使用appdomain
    函数族中的
    msclr::call_。我在这里记录了我的最终解决方案:性能以微秒计。因此,在这之后,我将请求/响应的缓存添加为C++ STD::MAP。这允许快速查找以前请求的任何内容,而无需返回C层。我在上面附上了额外的信息。