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

相应的托管代码如下,

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

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

C++手动加载CLR运行托管程序(CLR Hosting)的更多相关文章

  1. [转] Linux下程序的加载、运行和终止流程

    TAG: linux, main, _start DATE: 2013-08-08 原文地址: http://blog.csdn.net/tigerscorpio/article/details/62 ...

  2. AngularJS中多个ng-app(手动加载模块)

    1.当有多个ng-app时:(首先是要加载angularJS) <div ng-app=""> <p>姓名:<input type="tex ...

  3. [Q]手动加载菜单方法

    一般情况下,安装程序会自动安装依云软件菜单,但可能由于某些原因未能自动安装的话,您可以手动加载菜单,步骤如下: 在AoutCAD命令行输入"CUILOAD",会弹出"加载 ...

  4. Linux进程启动过程分析do_execve(可执行程序的加载和运行)---Linux进程的管理与调度(十一)

    execve系统调用 execve系统调用 我们前面提到了, fork, vfork等复制出来的进程是父进程的一个副本, 那么如何我们想加载新的程序, 可以通过execve来加载和启动新的程序. x8 ...

  5. angularjs自动加载和手动加载

    (一)自动加载 ng-app是angular的一个指令,代表一个angular应用(也叫模块).使用ng-app或ng-app=""来标记一个DOM结点,让框架会自动加载.也就是说 ...

  6. 服务是如何加载并运行的, Kestrel、配置与环境

    服务是如何加载并运行的, Kestrel.配置与环境 "跨平台"后的ASP.Net Core是如何接收并处理请求的呢? 它的运行和处理机制和之前有什么不同? 本章从"宏观 ...

  7. 使用angular.bootstrap() 完成模块的手动加载

    之前我们看到使用ng-app指令,可以实现模块的自动加载.现在我们看下,angular中如何手动加载模块.需要使用到angular.bootstrap这个函数. <html> <he ...

  8. angularjs 手动加载

    利用ng-app可以完成自动加载,如果不利用ng-app.那么使用bootstrarp实现手动加载模块 <html> <head> <script src="a ...

  9. TP中手动加载类库

    加载第三方类库,包括不符合命名规范和后缀的类库,以及没有使用 命名空间或者空间和路径不一致的类库.可手动加载. // 导入Org类库包 Library/Org/Util/Date.class.php类 ...

随机推荐

  1. 老司机带你体验SYS库多种新玩法

    导读 如何更加愉快地利用sys库做一些监控? 快来,跟上老司机,体验sys库的多种新玩法~ MySQL5.7的新特性中,非常突出的特性之一就是sys库,不仅可以通过sys库完成MySQL信息的收集,还 ...

  2. Tomcat 端口配置及原理详解

    1. tomcat 文件配置详细说明 tomcat服务器需配置三个端口才能启动,安装时默认启用了这三个端口,当要运行多个tomcat服务时需要修改这三个端口,不能相同.端口配置路径为tomcat\ c ...

  3. 快速排序(C++)

    快速排序 快速排序是面试中经常问到的排序算法 基本思想:通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小, 则可分别对这两部分记录继续进行排序,以达到整个序 ...

  4. Qt5创建模态和非模态对话框

    1.模态对话框创建: 第一种方法: QDialog dialog(this); dialog.exec(); this为该对话框的父窗口. 第二种方法: QDialog *dialog = new Q ...

  5. 小白2分钟学会Visual Studio将引用包打包到NuGet上

    前言 之前我们说 10分钟学会Visual Studio将自己创建的类库打包到NuGet进行引用(net,net core,C#),过程有些许繁琐,并且需要有一定的基础. 怎么办呢,不慌,看法宝. 两 ...

  6. 【进阶之路】持续集成、持续交付与持续部署(CI/CD)

    由来 记得7月份刚刚换工作的时候,中午和老大一起去吃饭,回来的路上老大问我:"南橘,CI/CD有没有研究过?" 我隐隐约约在哪里听过这个名词,但是又想不起来,秉着实事求是的态度,我 ...

  7. Linux上使用设置printf显示的颜色

    我们经常看到别的屏幕五颜六色的很是羡慕,看着很炫是吧.其实我们也可以自己做一个简单的修改,是我们的显示结果也呈现出不同的颜色.shell脚本可能设置的比较多,但是我们平常使用C语言却很少设置它的颜色, ...

  8. jQuery-01

    day01 - jQuery 学习目标: 能够说出什么是 jQuery 能够说出 jQuery 的优点 能够简单使用 jQuery 能够说出 DOM 对象和 jQuery 对象的区别 能够写出常用的 ...

  9. Centos6.5时间服务器NTP搭建

    NTP时间服务器安装与配置 第1章 Server端的安装与配置 1.1 查看系统是否已经安装ntp服务组件 rpm -qa | grep "ntp" #<==查看是否已经安装 ...

  10. java线程day-02

    1.什么是线程 * 线程是程序执行的一条路径, 一个进程中可以包含多条线程 * 多线程并发执行可以提高程序的效率, 可以同时完成多项工作 2.多线程的应用场景 * 红蜘蛛同时共享屏幕给多个电脑 * 迅 ...