C#调用无导入头C++ DLL时类内导出函数找不到入口点如何解决
问题核心原因
C++编译器会对类内的成员函数、静态函数做*名字修饰(Name Mangling)*处理,DLL中实际导出的函数名不是你看到的GetInstance,而是类似?GetInstance@CRfebUsbApp@@SAPAV1@XZ这类带编译器规则前缀后缀的修饰后名称,直接用原函数名声明导入自然会提示找不到入口点。
解决步骤
第一步:获取实际导出函数名
用DLL Export Viewer打开目标DLL,找到CRfebUsbApp::GetInstance对应的完整导出名字段,直接复制完整的修饰后名称。第二步:修改C#导入声明,显式指定入口点
在DllImport属性中增加EntryPoint参数,值填写你刚复制的完整导出名,修改后的代码参考如下:[DllImport("lib/CmtRfebUsb.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?GetInstance@CRfebUsbApp@@SAPAV1@XZ")] public static extern IntPtr GetInstance();(可选)后续调用类内
__thiscall成员函数的处理规则
你提到其他导出函数都是__thiscall约定,这类是类普通成员函数,隐含第一个参数为类实例的this指针,调用时需要遵循以下规则:- 同样先查对应函数的修饰后导出名,填入
EntryPoint - 指定调用约定为
CallingConvention.ThisCall - 函数第一个参数显式声明为
IntPtr类型,用于传入GetInstance返回的类实例指针
示例(假设调用返回设备数量的成员函数
GetDeviceCount):[DllImport("lib/CmtRfebUsb.dll", CallingConvention = CallingConvention.ThisCall, EntryPoint = "你查到的对应导出名")] public static extern int GetDeviceCount(IntPtr thisPtr);- 同样先查对应函数的修饰后导出名,填入
注意事项
上述方案是在你无法修改C++ DLL源码的前提下的最优解法,如果可以修改DLL源码,给导出函数加
extern "C"修饰可以避免名字修饰问题,直接用原函数名导入即可。
内容的提问来源于stack exchange,提问作者Marco Arigliani
相关产品推荐
相关产品推荐

