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

    C++手动加载CLR运行托管程序(CLR Hosting)

    WebDebug 2012-10-14 14:18:32 4907 收藏
    分类专栏: Windows编程 文章标签: c++ string 开发工具 include 扩展 语言
    版权

    Windows编程
    专栏收录该内容
    2 篇文章0 订阅
    订阅专栏
    机制介绍
    有些时候主程序是通过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!

  • 相关阅读:
    go多平台编译打包
    正则表达式
    Java 线程安全问题的本质
    Thread interrupt() 线程中断的详细说明
    git -c diff.mnemonicprefix=false -c core.quotepath=false --no-optional-locks push -v --tags origin master:master Logon failed, use ctrl+c to cancel basic credential prompt.
    kafka 消费组功能验证以及消费者数据重复数据丢失问题说明 3
    kafka 副本机制和容错处理 -2
    Mat使用详解
    MySql Binlog 说明 & Canal 集成MySql的更新异常说明 & MySql Binlog 常用命令汇总
    ElasticSearch 集群基本概念及常用操作汇总(建议收藏)
  • 原文地址:https://www.cnblogs.com/guanshan/p/guan2021-11-04_002.html
Copyright © 2011-2022 走看看