动态加载和卸载非托管 DLL
使用 DllImport
属性时,你必须在编译时知道正确的 dll 和方法名称。如果你想要更灵活并在运行时决定加载哪些 dll 和方法,可以使用 Windows API 方法 LoadLibrary()
, GetProcAddress()
和 FreeLibrary()
。如果要使用的库取决于运行时条件,这可能会有所帮助。
GetProcAddress()
返回的指针可以使用 Marshal.GetDelegateForFunctionPointer()
转换为委托。
以下代码示例使用前面示例中的 myDLL.dll
演示了这一点:
class Program
{
// import necessary API as shown in other examples
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibrary(string lib);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void FreeLibrary(IntPtr module);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr module, string proc);
// declare a delegate with the required signature
private delegate int AddDelegate(int a, int b);
private static void Main()
{
// load the dll
IntPtr module = LoadLibrary("myDLL.dll");
if (module == IntPtr.Zero) // error handling
{
Console.WriteLine($"Could not load library: {Marshal.GetLastWin32Error()}");
return;
}
// get a "pointer" to the method
IntPtr method = GetProcAddress(module, "add");
if (method == IntPtr.Zero) // error handling
{
Console.WriteLine($"Could not load method: {Marshal.GetLastWin32Error()}");
FreeLibrary(module); // unload library
return;
}
// convert "pointer" to delegate
AddDelegate add = (AddDelegate)Marshal.GetDelegateForFunctionPointer(method, typeof(AddDelegate));
// use function
int result = add(750, 300);
// unload library
FreeLibrary(module);
}
}