NSIS自定义DLL运行报错‘Could not find symbol’求助
我正在为NSIS脚本制作自定义DLL,流程如下:
- 已创建导出目标函数的DLL文件,通过
dumpbin验证函数已成功导出 - 将DLL放置在插件目录,脚本中用
DLLName::FunctionName调用函数 - 编译器能识别插件目录中的DLL并关联函数,但运行安装程序时,每个DLL函数都会弹出
Could not find symbol: <Function Name>错误
针对这个问题,可从以下几个方向排查:
检查函数导出的名称修饰
C++编译默认会对函数名做名称修饰,比如原本的FunctionName会变成类似?FunctionName@@YAHXZ的格式,而NSIS需要无修饰的C风格名称。可以用dumpbin /exports yourdll.dll仔细核对导出的函数名是否和脚本中调用的完全一致。
解决办法:导出函数时用extern "C"声明,或者通过.def文件明确指定导出名称。示例.def文件:LIBRARY YourDllName EXPORTS FunctionName @1确认DLL与NSIS编译器的位数匹配
NSIS分32位和64位版本,如果你的DLL是64位却用32位NSIS编译安装包,或者反之,运行时会出现符号找不到的问题。
解决办法:对应NSIS的位数重新编译DLL,比如NSIS x86版本搭配32位DLL,NSIS x64版本搭配64位DLL。验证安装包中DLL的打包与路径
即使编译时DLL在插件目录,也可能出现安装包未正确打包DLL,或者运行时DLL所在路径不对的情况。
解决办法:检查安装包解压后的目录是否存在目标DLL;也可以在脚本中用SetOutPath指定DLL的运行路径,确保加载时能找到文件。核对函数调用约定
NSIS插件函数要求使用__stdcall调用约定,如果误用__cdecl,会因调用约定差异导致名称修饰或调用失败,进而出现找不到符号的错误。
解决办法:导出函数时明确指定__stdcall,比如:extern "C" __declspec(dllexport) int __stdcall FunctionName() { // 函数逻辑 }或者在.def文件中声明导出,.def文件会自动处理调用约定的名称修饰问题。
确认DLL导出方式的正确性
相比__declspec(dllexport),使用.def文件导出函数更可靠,能避免C++名称修饰的干扰,确保导出的名称完全符合脚本中的调用名。
内容的提问来源于stack exchange,提问作者KGN

