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!

  • 相关阅读:
    [算法] 堆栈
    [刷题] PTA 02-线性结构3 Reversing Linked List
    java IO流 (八) RandomAccessFile的使用
    java IO流 (七) 对象流的使用
    java IO流 (六) 其它的流的使用
    java IO流 (五) 转换流的使用 以及编码集
    java IO流 (四) 缓冲流的使用
    java IO流 (三) 节点流(或文件流)
    java IO流 (二) IO流概述
    java IO流 (一) File类的使用
  • 原文地址:https://www.cnblogs.com/guanshan/p/guan2021-11-04_002.html
Copyright © 2011-2022 走看看