macOS下Free Pascal生成的dylib符号可被nm查看却无法被dlsym定位
问题
在Apple Silicon架构的macOS系统上,使用Free Pascal 3.2.2编译生成.dylib动态库时遇到异常:
- 动态库在Windows环境下可正常调用导出函数
- macOS中用
nm命令能看到符号表中的导出符号,但通过dlsym无法查找成功 - 库可以正常加载,但
dlsym返回NULL,报错"symbol not found"
相关代码与输出
- Free Pascal导出代码:
exports GetName name 'GetName', GetBid name 'GetBid', GetCard name 'GetCard';
nm命令查看符号表结果:
$ nm -gU libplayer.dylib 0000000000005360 T GetBid 0000000000005370 T GetCard 0000000000005350 T GetName
- C语言调用代码:
void* handle = dlopen("./libplayer.dylib", RTLD_LAZY); // 加载成功 void* symbol = dlsym(handle, "GetName"); // 返回NULL printf("Error: %s\n", dlerror()); // 输出"symbol not found"
- 编译参数:
-fPIC -k-no_order_inits -k-dylib
原因分析
macOS动态链接器对符号可见性有严格限制,Free Pascal默认编译逻辑下,即使通过exports声明符号,也可能未将其标记为全局可见属性。另外Apple Silicon架构的Mach-O格式符号导出规则和Windows PE格式不同,Windows上的导出方式无法直接适配macOS环境——nm能显示符号仅代表符号存在于表中,但不代表它对外暴露可被dlsym访问。
解决方法
方法1:添加链接器参数强制导出符号
编译时添加链接器参数,通过符号列表文件指定需要对外导出的符号:
- 创建一个文本文件
symbols.txt,列出带下划线前缀的符号(Free Pascal在macOS下会自动给符号加下划线):
_GetName _GetBid _GetCard
- 修改编译命令,加入导出符号列表的参数:
fpc -fPIC -k-no_order_inits -k-dylib -k"-exported_symbols_list symbols.txt" yourlibrary.pas
方法2:使用编译指令强制导出所有符号
在Pascal代码开头添加{$EXPORTALL ON}指令,强制导出所有符号(适合测试场景,正式环境不推荐,会增大库体积):
{$EXPORTALL ON} exports GetName name 'GetName', GetBid name 'GetBid', GetCard name 'GetCard';
方法3:验证符号可见性
用otool命令检查符号的实际属性,确认是否为对外可见:
otool -lv libplayer.dylib | grep -A 5 -B 5 GetName
如果输出中type字段为non-external,说明符号未对外导出,需要调整编译参数使其变为external。
内容的提问来源于stack exchange,提问作者Bilko
相关产品推荐
相关产品推荐

