C#中动态加载C++ DLL文件
在C#中动态加载C++ DLL(动态链接库)可以通过几种方式实现。下面我将介绍最常用的方法:
1. 使用DllImport特性(静态加载)
这是最常见的方式,虽然不是完全动态的,但值得了解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| using System; using System.Runtime.InteropServices;
class Program { [DllImport("YourCppDll.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int YourCppFunction(int param1, string param2);
static void Main() { int result = YourCppFunction(123, "test"); Console.WriteLine($"Result: {result}"); } }
|
2. 使用LoadLibrary和GetProcAddress(真正动态加载)
如果你想在运行时决定加载哪个DLL,可以使用Windows API:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| using System; using System.Runtime.InteropServices;
class Program { [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll", SetLastError = true)] public static extern bool FreeLibrary(IntPtr hModule);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate int YourCppFunctionDelegate(int param1, string param2);
static void Main() { IntPtr pDll = LoadLibrary(@"YourCppDll.dll"); if (pDll == IntPtr.Zero) { Console.WriteLine("Failed to load DLL"); return; }
IntPtr pAddressOfFunctionToCall = GetProcAddress(pDll, "YourCppFunction"); if (pAddressOfFunctionToCall == IntPtr.Zero) { Console.WriteLine("Failed to find function"); FreeLibrary(pDll); return; }
YourCppFunctionDelegate yourFunction = Marshal.GetDelegateForFunctionPointer<YourCppFunctionDelegate>(pAddressOfFunctionToCall);
int result = yourFunction(123, "test"); Console.WriteLine($"Result: {result}");
FreeLibrary(pDll); } }
|
如果C++ DLL是COM组件,可以使用COM互操作:
1 2 3
| Type comType = Type.GetTypeFromProgID("YourCOMComponent.YourClass"); dynamic comObject = Activator.CreateInstance(comType); comObject.YourMethod(123, "test");
|
注意事项
调用约定:确保C#端和C++端的调用约定一致(通常C++使用__cdecl
或__stdcall
)。
数据类型映射:注意C++和C#之间的数据类型转换,特别是字符串和指针类型。
32/64位兼容性:确保DLL和应用程序的平台架构一致(同为x86或x64)。
DLL位置:DLL文件需要放在应用程序可找到的路径(如exe所在目录或系统PATH中)。
内存管理:如果DLL分配内存,确保有相应的释放机制,避免内存泄漏。
异常处理:C++异常不能直接传递到C#,需要在C++端捕获并转换为错误码。