zoukankan      html  css  js  c++  java
  • 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了

  • 相关阅读:
    2020以去过半,写一下上半年的总结跟下半年的计划
    js实现浏览器打印功能
    看不见远程新建git分支
    Vue中导出Excel表格方法
    SVN命令使用详解
    IOS NSTimer 定时器用法总结
    静态库与动态库的区别?
    iOS 本地缓存实现 方案借鉴
    IOS开发中NSRunloop跟NSTimer的问题
    FMDB
  • 原文地址:https://www.cnblogs.com/flyDream12315/p/6062920.html
Copyright © 2011-2022 走看看