C++调用dotnet-第一节(ICLRRuntimeInfo加载宿主方式)

C++调用dotnet-第一节(ICLRRuntimeInfo加载宿主方式)

-------C++手动加载clr调用托管代码(非com方式)

注:目前非托管C++调用.NET托管代码,主要有两种方式(1.通过CLR提供的接口CLRRuntimeInfo在c++中加载clr然后通过clr调用托管代码;2.讲dotnet托管代码封装成com的方式)本文先讲解第一张

第一种方式与第二种方式对比:

CLR Hosting宿主方式:

                               A劣势: 调用方法签名只能是固定的形式[static int mathName(string paramstr))];另外在测试过程中发现弹窗操作提示为非法操作(理解为不能进行弹窗等涉及安全的操作);c++方调用较                                            为复杂(不过形式固定,第一次封装后,后面就方便了)

                               B优势:托管语言开发简单,部署简单方便

COM封装托管代码方式:

                               A劣势:开发较第一种复杂(需要托管代码中按com的开发模式进行封装,加载到GAC中还需要强命名)、部署环境也复杂(需要注册COM)

                               B优势:形式多样,可以继续弹框,甚至参数可以是类,结构体等;c++调用时方便

托管语言c#开发没有特殊要求,直接像平常开发dll一样,只要方法签名满足(静态,返回值为int,输入参数为一个string类型)就可以了

如下:

 1 using IMWpfLib;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 
 8 namespace CLRHostLib
 9 {
10     public class ClrClass
11     {
12         public static int ClrExcute(string paramstr) {
13 
14             Console.WriteLine("调用成功");
15             IMComInterop cc = new IMComInterop();
16             //这句代码中有弹框操作,会报错,不能有弹框之类涉及到用户安全的操作(弹框干涉到用户界面操作了)
17             cc.ShowWindowsTest();
18             return 1;
19         }
20 
21     }
22 }

c++方面稍微复杂一点

第一步:将之前编译的dll拷贝到exe所在目录

 

第二步:新建一个win32 控制台程序,添加调用所需的DotNetRuntimeWrap类(下面是头文件和cpp文件)
注意:下面截图这几行代码必须加上,网上很多例子没有这几行,调用ExecuteInDefaultAppDomain提示无法找到对应的类
#pragma once


//#include <Windows.h>
//#include <stdio.h>
//#include <iostream>
//#include <mscoree.h>
//#include <metahost.h>
//#include <assert.h>
//#pragma comment(lib, "mscoree.lib")
#define BUFFER_SIZE 500
//#include "stdafx.h"
//
//
//
//
// using namespace std;

#include <windows.h>

#include <metahost.h>
#pragma comment(lib, "mscoree.lib")

// Import mscorlib.tlb (Microsoft Common Language Runtime Class Library).
#import "mscorlib.tlb" raw_interfaces_only                
    high_property_prefixes("_get","_put","_putref")        
    rename("ReportEvent", "InteropServices_ReportEvent")
using namespace mscorlib;

class DotNetRuntimeWrap
    {
    public:
        DotNetRuntimeWrap(void);
        ~DotNetRuntimeWrap(void);
    public:    void StartTheDotNetRuntime(LPCWSTR runtimeVersion, LPCWSTR dllPath, LPCWSTR startClass, LPCWSTR startMethod, LPCWSTR startArgument);
            /************************************************* 
            加载托管dll调用入口
            *************************************************/  
    public:    void Loader(LPCWSTR donnetVersion,LPCWSTR clrDllFullName,LPCWSTR clrClassFullName,LPCWSTR clrMathName);
    public:    void Test();
    };
 1 #include "stdafx.h"
 2 #include "DotNetRuntimeWrap.h"
 3 
 4 
 5 DotNetRuntimeWrap::DotNetRuntimeWrap(void)
 6     {
 7 
 8     }
 9 
10 
11 DotNetRuntimeWrap::~DotNetRuntimeWrap(void)
12     {
13     }
14 
15 void DotNetRuntimeWrap::StartTheDotNetRuntime(LPCWSTR runtimeVersion, LPCWSTR dllPath, LPCWSTR startClass, LPCWSTR startMethod, LPCWSTR startArgument)
16     {
17     ICLRMetaHost *pMetaHost = NULL;
18     ICLRMetaHostPolicy *pMetaHostPolicy = NULL;
19     ICLRDebugging *pCLRDebugging = NULL;
20     CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost);
21     CLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, (LPVOID*)&pMetaHostPolicy);
22     CLRCreateInstance(CLSID_CLRDebugging, IID_ICLRDebugging, (LPVOID*)&pCLRDebugging);
23     DWORD dwVersion = 0;
24     DWORD dwImageVersion = 0;
25     ICLRRuntimeInfo *pRuntimeInfo;
26     HRESULT result;
27     result = pMetaHost->GetRuntime(runtimeVersion, IID_ICLRRuntimeInfo, (LPVOID*)&pRuntimeInfo);
28     assert(SUCCEEDED(result));
29     ICLRRuntimeHost * pRuntimeHost = NULL;
30     result = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&pRuntimeHost);
31     assert(SUCCEEDED(result));
32     result = pRuntimeHost->Start();
33     assert(SUCCEEDED(result));
34     DWORD dwRetCode = 0;
35     result = pRuntimeHost->ExecuteInDefaultAppDomain(dllPath, startClass, startMethod, startArgument, &dwRetCode);
36     assert(SUCCEEDED(result));
37     pRuntimeHost->Stop();
38     pRuntimeHost->Release();
39     pRuntimeInfo->Release();
40     pCLRDebugging->Release();
41     pMetaHostPolicy->Release();
42     pMetaHost->Release();
43     }
44 
45 
46 void DotNetRuntimeWrap::Loader(LPCWSTR donnetVersion,LPCWSTR clrDllFullName,LPCWSTR clrClassFullName,LPCWSTR clrMathName)
47     {
48     wchar_t* runtimeVersionSpace = new wchar_t[BUFFER_SIZE];
49     wchar_t* dllPathSpace = new wchar_t[BUFFER_SIZE];
50     wchar_t* currentDir = new wchar_t[BUFFER_SIZE];
51     GetCurrentDirectoryW(BUFFER_SIZE, currentDir);
52     StartTheDotNetRuntime(donnetVersion,clrDllFullName,clrClassFullName,clrMathName, L"");
53     //StartTheDotNetRuntime(L"v4.0.30319", L"ClassLibrary1.dll", L"ClassLibrary1.Class1", L"EntryPoint", L"");
54     free(runtimeVersionSpace);
55     free(dllPathSpace);
56     free(currentDir);
57     }
58 void DotNetRuntimeWrap::Test()
59     {
60     }

 下面是调用方式

 1 #include "stdafx.h"
 2 #include <iostream>
 3 #include "DotNetRuntimeWrap.h"
 4 
 5 static void TestClrHost()
 6     {
 7 
 8     DotNetRuntimeWrap dotNetWrap;
 9     dotNetWrap.Loader(L"v4.0.30319", L"CLRHostLib.dll", 
10         L"CLRHostLib.ClrClass",L"ClrExcute");
11 
12     }
13 
14 int _tmain(int argc, _TCHAR* argv[])
15     {
16 
17     TestClrHost();
18 
19     return 0;
20     }

运行结果:普通操作一切正常,不过执行弹框的时候会出错(下面截图断点这一行里面有弹框操作),规避这类操作,运行就OK了

原文地址:https://www.cnblogs.com/flyDream12315/p/6062920.html