zoukankan      html  css  js  c++  java
  • C++手动加载CLR运行托管程序(CLR Hosting)

    转载自:http://www.linuxidc.com/Linux/2012-10/72293.htm

    机制介绍

    有些时候主程序是通过C/C++实现的,但是我们希望通过托管代码来扩展非托管程序,从而也获得托管代码带来的一系列优点。比如开发效率高,自动垃圾回收等。

    运行托管与非托管代码根本区别在于托管代码是进程首先加载CLR然后通过CLR运行托管程序,而非托管代码则是操作系统直接根据其PE Header加载程序分配内存从而运行。因此如果需要通过托管代码来扩展非托管程序,首先要加载CLR来使非托管程序获得运行托管代码的能力。

    可以使用以下过程将 CLR 加载到进程中:

    1. 调用 CLRCreateInstance 函数以获取 ICLRMetaHost 或 ICLRMetaHostPolicy 接口。 CLRCreateInstance 函数取代 .NET Framework 1.1 和 2.0 承载全局静态函数部分中列出的所有 CorBindTo* 函数。
    2. 调用 ICLRMetaHost::EnumerateInstalledRuntimes、ICLRMetaHost::GetRuntime 或 ICLRMetaHostPolicy::GetRequestedRuntime 方法以获取有效的 ICLRRuntimeInfo 指针。
    3. 调用 ICLRRuntimeInfo::GetInterface 方法。 为 rclsid 参数指定 CLSID_CLRRuntimeHost,并为 riid 参数指定 IID_ICLRRuntimeHost。

    所有这些接口的原型均位于 Metahost.h 文件中,该文件位于 Windows 软件开发工具包 (SDK) 的 Include 目录中。 宿主可以使用 ICLRRuntimeInfo 和 ICLRRuntimeHost 接口来控制要加载哪个版本的运行时以及基本功能(如垃圾回收和程序集加载)的行为。使用 ICLRRuntimeHost 接口可以执行以下操作:

    1. 通过调用 ICLRRuntimeHost::Start 方法来启动运行时。
    2. 执行托管代码。
    3. 获取指向 ICLRControl 接口(可提供对由公共语言运行时实现的管理器的访问)的指针,以及注册实现 IHostControl 接口的宿主控件对象。 公共语言运行时调用 IHostControl 接口来确定宿主实现的管理器。

    参考这里 http://msdn.microsoft.com/en-us/library/01918c6x.aspx

    实例代码

    以下是C++加载CLR运行托管程序的实例代码,启动CLR之后通过调用ExecuteInDefaultAppDomain来运行托管程序SampleManagedApp.exe中名为Test的程序。这里要注意的是ExecuteInDefaultAppDomain只能执行托管代码签名为static int pwzMethodName (String pwzArgument)的方法。

    1. #include <SDKDDKVer.h>  
    2.  
    3. #include <stdio.h>  
    4. #include <tchar.h>  
    5. #include <windows.h>  
    6.  
    7. #include <metahost.h>  
    8. #include <mscoree.h>  
    9. #pragma comment(lib, "mscoree.lib")  
    10.  
    11. int _tmain(int argc, _TCHAR* argv[]) 
    12.     ICLRMetaHost        *pMetaHost = nullptr; 
    13.     ICLRMetaHostPolicy  *pMetaHostPolicy = nullptr; 
    14.     ICLRRuntimeHost     *pRuntimeHost = nullptr; 
    15.     ICLRRuntimeInfo     *pRuntimeInfo = nullptr; 
    16.  
    17.     HRESULT hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost); 
    18.     hr = pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo)); 
    19.  
    20.     if(FAILED(hr)) 
    21.     { 
    22.         goto cleanup; 
    23.     } 
    24.  
    25.     hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&pRuntimeHost)); 
    26.  
    27.     hr = pRuntimeHost->Start(); 
    28.  
    29.     DWORD dwRet = 0; 
    30.     hr = pRuntimeHost->ExecuteInDefaultAppDomain(L"SampleManagedApp.exe", 
    31.                                                  L"SampleManagedApp.Program",   
    32.                                                  L"Test", 
    33.                                                  L"Hello World!", 
    34.                                                  &dwRet); 
    35.  
    36.     hr = pRuntimeHost->Stop(); 
    37.  
    38. cleanup: 
    39.     if(pRuntimeInfo != nullptr) 
    40.     { 
    41.         pRuntimeInfo->Release(); 
    42.         pRuntimeInfo = nullptr; 
    43.     } 
    44.  
    45.     if(pRuntimeHost != nullptr) 
    46.     { 
    47.         pRuntimeHost->Release(); 
    48.         pRuntimeHost = nullptr; 
    49.     } 
    50.  
    51.     if(pMetaHost != nullptr) 
    52.     { 
    53.         pMetaHost->Release(); 
    54.         pMetaHost = nullptr; 
    55.     } 

    相应的托管代码如下,

    1. using System; 
    2.  
    3. namespace SampleManagedApp 
    4.     class Program 
    5.     { 
    6.         static void Main(string[] args) 
    7.         { 
    8.         } 
    9.  
    10.         public static int Test(string s) 
    11.         { 
    12.             Console.WriteLine(s); 
    13.             return 0; 
    14.         } 
    15.     } 

    最终将SampleManagedApp.exe与非托管程序放在同一个路径下运行非托管程序,就会得到最终Console中输出:Hello World!

  • 相关阅读:
    125. Valid Palindrome java solutions
    350. Intersection of Two Arrays II java solutions
    ex25.py 各种函数
    习题21,几个简单的加减乘除函数,注意return的用法。
    文件的写入,但是出了一个bug。(Unicode解码错误:‘gbk’编解码器无法解码位置0中的字节0xff:非法多字节序列)
    读写文件(open(), write())
    who, w, whoami以及id命令的使用
    终端设备与tty、chvt、startx命令
    设置自动登录CentOS7
    docker常用命令
  • 原文地址:https://www.cnblogs.com/bizca/p/6079092.html
Copyright © 2011-2022 走看看