如何在C#中调用原生C++ DLL中未导出的函数?
在C#中调用未导出的C++ DLL函数
实现步骤与代码
要在C#中调用未导出的C++ DLL函数,需要借助Win32 API加载DLL、计算函数地址,再通过委托完成调用,具体如下:
定义Win32 API的P/Invoke声明
用于加载和释放DLL模块:using System; using System.Runtime.InteropServices; public static class Win32 { [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern IntPtr LoadLibrary(string lpFileName); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool FreeLibrary(IntPtr hModule); }定义匹配函数签名的委托
必须指定Cdecl调用约定,与C++中的_cdecl保持一致:[UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void TfFunc(int param1, ref IntPtr data);这里用
ref IntPtr对应C++的unsigned char**,IntPtr可直接表示非托管指针,ref则对应指针的引用。加载DLL并调用目标函数
public static void CallUnExportedFunction() { // 加载目标DLL IntPtr moduleHandle = Win32.LoadLibrary("A.dll"); if (moduleHandle == IntPtr.Zero) { throw new System.ComponentModel.Win32Exception(); } try { // 计算函数绝对地址:模块基址 + 给定偏移 IntPtr funcAddress = IntPtr.Add(moduleHandle, 0x00003E89D); // 将地址转换为委托实例(.NET Core/.NET 5+可使用泛型版本简化) // TfFunc func = Marshal.GetDelegateForFunctionPointer<TfFunc>(funcAddress); TfFunc func = (TfFunc)Marshal.GetDelegateForFunctionPointer(funcAddress, typeof(TfFunc)); // 调用函数,传入对应参数 IntPtr dataPtr = IntPtr.Zero; func(1, ref dataPtr); } finally { // 释放DLL句柄 Win32.FreeLibrary(moduleHandle); } }
关键注意事项
- 调用约定必须严格匹配:如果委托未指定
CallingConvention.Cdecl,会导致栈损坏、程序崩溃。 - 参数类型对应准确:
unsigned char**需用ref IntPtr对应,若函数会修改传入指针,必须使用ref或out关键字。 - 偏移有效性:确保给定偏移是相对于DLL加载基址的相对虚拟地址(RVA),Windows会自动处理基址重定位,偏移无需手动调整。
- 错误处理:加载DLL失败时,可通过
Marshal.GetLastWin32Error()获取具体错误码排查问题。
内容的提问来源于stack exchange,提问作者Louka
相关产品推荐
相关产品推荐

