標籤:hosting 介紹 clr 運行 proc 全域 goto tco 注意
轉載自:http://www.linuxidc.com/Linux/2012-10/72293.htm機制介紹
有些時候主程式是通過C/C++實現的,但是我們希望通過Managed 程式碼來擴充非託管程式,從而也獲得Managed 程式碼帶來的一系列優點。比如開發效率高,自動記憶體回收等。
運行託管與Unmanaged 程式碼根本區別在於Managed 程式碼是進程首先載入CLR然後通過CLR運行託管程式,而Unmanaged 程式碼則是作業系統直接根據其PE Header載入程式分配記憶體從而運行。因此如果需要通過Managed 程式碼來擴充非託管程式,首先要載入CLR來使非託管程式獲得運行Managed 程式碼的能力。
可以使用以下過程將 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 方法來啟動運行時。
- 執行Managed 程式碼。
- 擷取指向 ICLRControl 介面(可提供對由通用語言執行平台實現的管理器的訪問)的指標,以及註冊實現 IHostControl 介面的宿主控制項對象。 通用語言執行平台調用 IHostControl 介面來確定宿主實現的管理器。
參考這裡 http://msdn.microsoft.com/en-us/library/01918c6x.aspx
執行個體代碼
以下是C++載入CLR運行託管程式的執行個體代碼,啟動CLR之後通過調用ExecuteInDefaultAppDomain來運行託管程式SampleManagedApp.exe中名為Test的程式。這裡要注意的是ExecuteInDefaultAppDomain只能執行Managed 程式碼簽名為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;
- }
- }
相應的Managed 程式碼如下,
- 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)