C++手动加载CLR运行托管程序(CLR Hosting)
转载自:http://www.linuxidc.com/Linux/2012-10/72293.htm
机制介绍
有些时候主程序是通过C/C++实现的,但是我们希望通过托管代码来扩展非托管程序,从而也获得托管代码带来的一系列优点。比如开发效率高,自动垃圾回收等。
运行托管与非托管代码根本区别在于托管代码是进程首先加载CLR然后通过CLR运行托管程序,而非托管代码则是操作系统直接根据其PE Header加载程序分配内存从而运行。因此如果需要通过托管代码来扩展非托管程序,首先要加载CLR来使非托管程序获得运行托管代码的能力。
可以使用以下过程将 CLR 加载到进程中:
- 调用 CLRCreateInstance 函数以获取 ICLRMetaHost 或 ICLRMetaHostPolicy 接口。 CLRCreateInstance 函数取代 .NET Framework 1.1 和 2.0 承载全局静态函数部分中列出的所有 CorBindTo* 函数。
- 调用 ICLRMetaHost::EnumerateInstalledRuntimes、ICLRMetaHost::GetRuntime 或 ICLRMetaHostPolicy::GetRequestedRuntime 方法以获取有效的 ICLRRuntimeInfo 指针。
- 调用 ICLRRuntimeInfo::GetInterface 方法。 为 rclsid 参数指定 CLSID_CLRRuntimeHost,并为 riid 参数指定 IID_ICLRRuntimeHost。
所有这些接口的原型均位于 Metahost.h 文件中,该文件位于 Windows 软件开发工具包 (SDK) 的 Include 目录中。 宿主可以使用 ICLRRuntimeInfo 和 ICLRRuntimeHost 接口来控制要加载哪个版本的运行时以及基本功能(如垃圾回收和程序集加载)的行为。使用 ICLRRuntimeHost 接口可以执行以下操作:
- 通过调用 ICLRRuntimeHost::Start 方法来启动运行时。
- 执行托管代码。
- 获取指向 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)的方法。
- #include <SDKDDKVer.h>
- #include <stdio.h>
- #include <tchar.h>
- #include <windows.h>
- #include <metahost.h>
- #include <mscoree.h>
- #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))
- {
- goto cleanup;
- }
- hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&pRuntimeHost));
- hr = pRuntimeHost->Start();
- DWORD dwRet = 0;
- hr = pRuntimeHost->ExecuteInDefaultAppDomain(L"SampleManagedApp.exe",
- L"SampleManagedApp.Program",
- L"Test",
- L"Hello World!",
- &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;
- }
- }
相应的托管代码如下,
- using System;
- namespace SampleManagedApp
- {
- class Program
- {
- static void Main(string[] args)
- {
- }
- public static int Test(string s)
- {
- Console.WriteLine(s);
- return 0;
- }
- }
- }
最终将SampleManagedApp.exe与非托管程序放在同一个路径下运行非托管程序,就会得到最终Console中输出:Hello World!
C++手动加载CLR运行托管程序(CLR Hosting)的更多相关文章
- [转] Linux下程序的加载、运行和终止流程
TAG: linux, main, _start DATE: 2013-08-08 原文地址: http://blog.csdn.net/tigerscorpio/article/details/62 ...
- AngularJS中多个ng-app(手动加载模块)
1.当有多个ng-app时:(首先是要加载angularJS) <div ng-app=""> <p>姓名:<input type="tex ...
- [Q]手动加载菜单方法
一般情况下,安装程序会自动安装依云软件菜单,但可能由于某些原因未能自动安装的话,您可以手动加载菜单,步骤如下: 在AoutCAD命令行输入"CUILOAD",会弹出"加载 ...
- Linux进程启动过程分析do_execve(可执行程序的加载和运行)---Linux进程的管理与调度(十一)
execve系统调用 execve系统调用 我们前面提到了, fork, vfork等复制出来的进程是父进程的一个副本, 那么如何我们想加载新的程序, 可以通过execve来加载和启动新的程序. x8 ...
- angularjs自动加载和手动加载
(一)自动加载 ng-app是angular的一个指令,代表一个angular应用(也叫模块).使用ng-app或ng-app=""来标记一个DOM结点,让框架会自动加载.也就是说 ...
- 服务是如何加载并运行的, Kestrel、配置与环境
服务是如何加载并运行的, Kestrel.配置与环境 "跨平台"后的ASP.Net Core是如何接收并处理请求的呢? 它的运行和处理机制和之前有什么不同? 本章从"宏观 ...
- 使用angular.bootstrap() 完成模块的手动加载
之前我们看到使用ng-app指令,可以实现模块的自动加载.现在我们看下,angular中如何手动加载模块.需要使用到angular.bootstrap这个函数. <html> <he ...
- angularjs 手动加载
利用ng-app可以完成自动加载,如果不利用ng-app.那么使用bootstrarp实现手动加载模块 <html> <head> <script src="a ...
- TP中手动加载类库
加载第三方类库,包括不符合命名规范和后缀的类库,以及没有使用 命名空间或者空间和路径不一致的类库.可手动加载. // 导入Org类库包 Library/Org/Util/Date.class.php类 ...
随机推荐
- MySQL binlog 自动清理脚本
# vim /data/scripts/delete_mysql_binlog.sh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ...
- vue系统总结2
注册组件 组件其他补充 组件数据存放 父子组件通信 父级向子级传递信息 子级向父级传递信息 插槽slot 1.1什么是组件化 1.2 注册组件的基本步骤 创建组件构造器 注册组件 使用组件 <d ...
- Ubuntu / CoreOS修改DNS配置
不要直接手动修改文件 /etc/resolv.conf 安装好Ubuntu之后设置了静态IP地址,再重启后就无法解析域名.想重新设置一下DNS,打开/etc/resolv.conf cat /etc/ ...
- 开源自己编写的半人工标注平台PaddleOCRLabel(.NET Winform版本)
大家好, 我是博客园的老用户了,许久不做.NET技术了,从2013年起,开始从事App技术,写过书,在Linux上搭建区块链,用GO写智能合约,使用nodejs搭建过微服务,用python写过爬虫,写 ...
- Zookeeper Acl权限 超级用户权限 怎么跳过ACL密码/账户验证
Zookeeper的一个节点不知道什么原因无法删除了,查看日志发现是没有权限, 我们之前使用ACL进行Zookeeper节点的权限管理. 可以解决以下三种但不限于以下三种问题: 1.在设置Acl权限时 ...
- djang2.1教育平台02
在次申明,之所以重做这个资料是因为原幕课教程漏洞太多,新手根本没有办法正常照些学习,我凭着老男孩python 课程基础,重做这个教程 ,更改版本为当前最新版本,为了方法以后的人学习,并不是照着原文照 ...
- C# 动态构建表达式树(二)——构建 Select 和 GroupBy 的表达式
C# 动态构建表达式树(二)--构建 Select 和 GroupBy 的表达式 前言 在上篇中写了表达式的基本使用,为 Where 方法动态构建了表达式.在这篇中会写如何为 Select 和 Gro ...
- java版gRPC实战之七:基于eureka的注册发现
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- PHP的可变变量与可变函数
什么叫可变.在程序世界中,可变的当然是变量.常量在定义之后都是不可变的,在程序执行过程中,这个常量都是不能修改的.但是变量却不同,它们可以修改.那么可变变量和可变函数又是什么意思呢?很明显,就是用另一 ...
- Linux命令进阶篇之二
实验内容: cat :由第一行开始显示文件内容 tac:由最后一行开始显示,有没有发现和cat是反过来写的 more:一页一页的显示内容 less:与more相似, ...