C++调用C#dll类库中的法门(非显性COM)

       
一般以网上搜C++如何调用C#的函数,出来的结果尚且是做成COM组件,但是这种方法dll安装麻烦,需要报COM组件,需要管理员权限,调试麻烦,经常用重新开机器,反正有紧。

        然后当圈《CLR via
C#》时相同一种方式,可以免去这种不快。少废话,先上代码。

C#类库的:

namespace ClassLibrary1
{
    public class Class1
    {
        public static int pwzMethodName(String pwzArgument)
        {
            //Thread.Sleep(10000);
            Console.WriteLine(pwzArgument);
            Console.WriteLine(Thread.GetDomain().FriendlyName);
        }
    }
}

C++调用代码:

#include <metahost.h>
#include <fstream>
using namespace std;

#pragma comment(lib, "mscoree.lib")

int _tmain(int argc, _TCHAR* argv[])
{
    ICLRMetaHost *pMetaHost = nullptr;
    ICLRMetaHostPolicy *pMetaHostPolicy = nullptr; 
    ICLRRuntimeHost *pRuntimeHost = nullptr; 
    ICLRRuntimeInfo *pRuntimeInfo = nullptr; 

    HRESULT hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost); 
    hr = pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo)); 

    if(FAILED(hr)) { 
        MessageBox(0,L"启动出错",L"Error",MB_OK|MB_ICONERROR);
        goto cleanup; 
    } 

    hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&pRuntimeHost)); 
    hr = pRuntimeHost->Start(); 

    DWORD dwRet = 0; 
    hr = pRuntimeHost->ExecuteInDefaultAppDomain(L"ClassLibrary1.dll", //不会产生新的进程
        L"ClassLibrary1.Class1", 
        L"pwzMethodName", 
        L"nimei", 
        &dwRet); 
    hr = pRuntimeHost->Stop(); 

cleanup: 
    if(pRuntimeInfo != nullptr) { 
        pRuntimeInfo->Release(); 
        pRuntimeInfo = nullptr; 
    } 

    if(pRuntimeHost != nullptr) { 
        pRuntimeHost->Release(); 
        pRuntimeHost = nullptr; 
    } 

    if(pMetaHost != nullptr) { 
        pMetaHost->Release(); 
        pMetaHost = nullptr; 
    } 
}

C#的代码就未讲了,就是提供一个int
ClassLibrary1.Class1.pwzMethodName(String)的这么一个办法。

首要看一下C++,它的思路就经过metahost.h中的函数来操作clr环境。

第一句,CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost,
(LPVOID*)&pMetaHost) 来初始化CLR环境,得到返回值pMetaHost。

第二句,pMetaHost->GetRuntime(L”v4.0.30319″,
IID_PPV_ARGS(&pRuntimeInfo))
来指定运行时,第一单参数.NET版本号,必须同你的C#dll的本号兼容,而且
此参数必须跟显在
C:\Windows\Microsoft.NET\Framework 或
C:\Windows\Microsoft.NET\Framework64 下的 .NET Framework
版本目录名称相匹配。比如,你的dll是因此4.0编译的,而若的Framework目录有瞬间文件夹:v2.0.50727  
v3.0   v3.5   v4.0.30319 ,所以这边的参数就是“v4.0.30319”,而且v是必须的。

第三句,pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost,
IID_PPV_ARGS(&pRuntimeHost)) 将 CLR
加载到手上历程遭到,并回到运行时接口指针pRuntimeHost。

季句子,pRuntimeHost->Start() 将集体语言运行时 (CLR) 初始化到过程遭到。

第五句,pRuntimeHost->ExecuteInDefaultAppDomain

HRESULT ExecuteInDefaultAppDomain (
    [in] LPCWSTR pwzAssemblyPath,
    [in] LPCWSTR pwzTypeName, 
    [in] LPCWSTR pwzMethodName,
    [in] LPCWSTR pwzArgument,
    [out] DWORD *pReturnValue
);

pwzAssemblyPath是C#类库的门道和文书称,pwzTypeName是命名空间及类名,pwzMethodName是一旦调用的方名称,pwzArgument是只要传播的参数名称,pReturnValue是函数返回值。

末尾的都是释放语句。

相似看来,这种措施就能够调用int function(String
para)这样的函数,但是实际LPCWSTR 是WCHAR
*,既然是指针就可以传递对象,同样返回值也堪是结构体或者数组。

本例地址:http://files.cnblogs.com/files/chihirosan/CPPCS%E4%BA%A4%E4%BA%92.rar