首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 動態載入/卸載非託管 DLL 技巧:LoadLibrary + GetProcAddress + IL 包裝器

     編輯:關於C語言

場景

需呼叫無法修改的原生 C DLL,裡含靜態變量計數器。欲重置計數器,必須 FreeLibrary 卸載後 LoadLibrary 重載。C# DllImport 為靜態綁定,無法動態卸載,故改用 WinAPI 動態載入。

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 指令。

IL 包裝器 (Wrapper.il)

.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
    }
}

編譯與使用

  1. ilasm /dll Wrapper.il 產生 Wrapper.dll。
  2. 專案參考 Wrapper.dll。
  3. 呼叫:int i = Wrapper.SomeMethod(pfn);
  4. 最後 FreeLibrary(hModule); 釋放。

此技巧繞過 C# 無法直接呼叫函數指標的限制,實現真正的動態載入/卸載非託管 DLL。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved