C++ .so转DLL后DllImport提示找不到入口点的问题求助
排查步骤与解决方案
一、解决System.DllNotFoundException(不指定路径时)
- 确认DLL放置路径:将
bcl_rule_engine.dll复制到C#项目的输出目录(如bin/Debug/netX.x或bin/Release/netX.x),或者在项目中添加DLL文件,右键设置其复制到输出目录为“始终复制”。Windows下CLR会优先搜索程序运行目录、系统目录及PATH环境变量路径,确保DLL在这些搜索路径内。 - 匹配平台架构:用Dependencies工具查看
bcl_rule_engine.dll的架构(x86/x64),然后设置C#项目的目标平台(右键项目→属性→生成→平台目标)与DLL一致。例如DLL是x64编译的,C#项目不能设为x86,否则会因架构不匹配导致加载失败。
二、解决System.EntryPointNotFoundException(指定路径时)
这个错误核心是找到了DLL,但找不到对应的函数入口,按以下顺序排查:
1. 检查函数是否被正确导出
用Dependencies工具查看DLL的导出表(界面中“Exports”标签),确认你要调用的函数是否在列表中:
- 如果函数不在导出表中:需要在C代码中显式导出函数。在函数声明前添加
extern "C" __declspec(dllexport),禁用C名字修饰并标记为导出,示例:
注意:Linux下的遗留代码可能用了GCC的extern "C" __declspec(dllexport) int YourRuleEngineFunction(int param) { // 函数实现 }__attribute__((visibility("default")))来导出,转Windows时要替换为__declspec(dllexport)。
2. 匹配函数名(解决名字修饰问题)
如果导出表中的函数名是经过C++修饰的(比如_Z18YourRuleEngineFunctioni这类带前缀后缀的名字),说明没有用extern "C"声明:
- 要么修改C++代码添加
extern "C"重新编译; - 要么在C#的
DllImport中通过EntryPoint指定修饰后的名字,示例:[DllImport("bcl_rule_engine.dll", EntryPoint = "_Z18YourRuleEngineFunctioni", CallingConvention = CallingConvention.Cdecl)] public static extern int YourRuleEngineFunction(int param);
3. 匹配调用约定
C#的DllImport默认使用StdCall调用约定,而C++(尤其是VS编译的C++代码)默认使用Cdecl调用约定,两者不匹配会导致入口点找不到或调用崩溃:
- 在
DllImport中显式指定调用约定,示例:
可以通过Dependencies工具查看导出函数的调用约定(导出表中函数名后的括号内会标注,比如[DllImport("bcl_rule_engine.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int YourRuleEngineFunction(int param);(cdecl))。
4. 修正库编译类型
你提到将原SHARED库改为STATIC解决链接错误,但静态库(.lib)无法被C#通过DllImport直接加载,必须编译为动态库(.dll)。需要调整CMake配置:
- 将
BUILD_SHARED_LIBS设为ON,确保生成动态链接库; - 如果静态库是依赖项,将其链接到动态库中,最终输出可被加载的
bcl_rule_engine.dll。
内容的提问来源于stack exchange,提问作者user3613025
相关产品推荐
相关产品推荐

