Native C++藉助CLR動態加載並調用.NET程序集

Native C++代碼和託管.NET代碼互操作並不是什麼難事, 資料也很多, 但是有些方法複雜繁瑣, 本文介紹了一種簡單的可行、支持動態加載的基於CLR的交互方法.


部分其它方法可參見 在 Visual C++/Native 代碼中調用.NET 程序集

微軟類似例子 C++/CLI wrapper for .NET assembly (CppCLINETAssem​blyWrapper), 該例子與本文類似, 只是通過編譯期引用方式, 不支持動態加載.


1.首先是動態加載目標程序集和類:

	try {
		auto assembly = Assembly::LoadFrom(L"RLib.dll"); // 加載 RLib.dll, 可指定路徑
		auto type     = assembly->GetType(L"RLib.Core", false, true); // 加載 RLib::Core 類型, 其中RLib是命名空間, Core是類名
		if (type != nullptr){ // 類型加載成功, 上面代碼指定了類型加載失敗不引發異常, 某些case下這非常有用
			// 注意此時 type 只是類對象, 並非實例
		} //if
	} catch (Exception ^ex) {

	}

2.其次得到並調用類成員/方法, 本文以靜態成員爲例:

	try {
		auto proc_init = type->GetMethod(L"Init"); // 取得 RLib::Core 類型的 public static int Init(int) 方法

		auto params = gcnew array<Object ^, 1>(1);
		params[0] = gcnew Int32(1); // int參數, 顯式裝箱

		auto ret = safe_cast<Int32 ^>(proc_init->Invoke(nullptr, params)); // 調用並取得返回值, 由於是靜態方法, 所以第一個參數指定爲 nullptr 即可

	} catch (Exception ^ex) {
	}

3.至此我們已經完成基本的代碼交互, 但是有時候我們需要保存託管對象以便反覆調用而不是重複加載, 直接加static修飾是不行的, 編譯不過,  解決方案大致有兩種, 一是使用GCHandle, 二是使用gcroot, 後者是對前者的包裝, 十分簡便, 示例如下:
		#include <gcroot.h>
		static gcroot<Assembly ^>   assembly = Assembly::LoadFrom(L"RLib.dll"); // 加載 RLib.dll, 可指定路徑
		assembly->CodeBase; // 直接使用 -> 操作符訪問
		assembly.operator Assembly ^ () == nullptr; // 判斷引用對象是否爲空, 這個需要顯式調用轉換


這只是最基本的交互方法, 更深層次的操作可以參閱MSDN文檔.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章