需呼叫無法修改的原生 C DLL,裡含靜態變量計數器。欲重置計數器,必須 FreeLibrary 卸載後 LoadLibrary 重載。C# DllImport 為靜態綁定,無法動態卸載,故改用 WinAPI 動態載入。
[DllImport("kernel32", EntryPoint="LoadLibrary", SetLastError=true)]
static extern IntPtr LoadLibrary(string lpLibName);
[DllImport("kernel32", EntryPoint="GetProcAddress", SetLastError=true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32", EntryPoint="FreeLibrary", SetLastError=true)]
static extern bool FreeLibrary(IntPtr hModule);
IntPtr hModule = LoadLibrary("ADll.dll");
IntPtr pfn = GetProcAddress(hModule, "GetValue");
關鍵難點:C# 無法直接呼叫函數指標。解法:編寫極簡 IL 組件包裝 calli 指令。
.assembly extern mscorlib {}
.assembly Wrapper {}
.class public Wrapper
{
.method public static int32 SomeMethod(native int pfn)
{
.maxstack 2
.locals (int32 V_0)
ldarg.0 // 推入函數指標
calli unmanaged stdcall int32() // 呼叫非託管函數
stloc.0
ldloc.0
ret
}
}
ilasm /dll Wrapper.il 產生 Wrapper.dll。Wrapper.dll。int i = Wrapper.SomeMethod(pfn);FreeLibrary(hModule); 釋放。此技巧繞過 C# 無法直接呼叫函數指標的限制,實現真正的動態載入/卸載非託管 DLL。