1. 程式人生 > >Native C++藉助CLR動態載入並呼叫.NET程式集

Native C++藉助CLR動態載入並呼叫.NET程式集

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

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文件.