为何iOS中无法用dlsym获取函数指针,Android却正常工作?
iOS下dlsym获取函数指针失败的解决方法
问题原因分析
- 调用约定不兼容:你在dylib源码中使用了Windows平台专属的
__stdcall调用约定,iOS/macOS不支持该约定,编译器会对符号做异常修饰,导致dlsym无法匹配到正确符号。 - 导出符号的方式错误:
__declspec(dllexport)是Windows平台的符号导出语法,在iOS/macOS环境下不生效,导致函数符号未被正确导出。
修正步骤
1. 修改dylib源码,适配iOS平台
将libSum.dylib的源码改为以下形式,使用苹果平台的标准符号导出规则,移除Windows专属语法:
extern "C" { __attribute__((visibility("default"))) int sum(int x, int y) { return x + y; } }
extern "C":确保函数符号以C语言规则生成,避免C++的名字修饰干扰。__attribute__((visibility("default"))):显式标记该函数为对外可见的导出符号,这是iOS/macOS平台导出动态库符号的标准方式。
2. 验证符号导出
重新编译dylib后,用命令行工具确认符号是否正确导出:
nm -g libSum.dylib
正常情况下会输出类似0000000000000f40 T _sum的结果,其中_sum就是可被dlsym识别的符号名。
3. 修正iOS端调用代码细节
- 用标准宏定义替代硬编码数字:将
dlopen的第二个参数从2改为RTLD_NOW,提升代码可读性和兼容性。 - 添加错误日志:调用
dlerror()获取dlsym失败的具体原因,便于排查问题。 - 确保库路径正确:优先通过Bundle获取库的绝对路径,避免沙盒路径问题。
修正后的iOS代码示例:
NSString *libPath = [[NSBundle mainBundle] pathForResource:@"libSum" ofType:@"dylib"]; const char *func_name = "_sum"; void *libHandle = dlopen([libPath UTF8String], RTLD_NOW); if (libHandle != NULL) { int (*sum)(int, int) = (int (*)(int, int))dlsym(libHandle, func_name); if (sum != NULL) { NSLog(@"%d", sum(5, 6)); } else { const char *errMsg = dlerror(); NSLog(@"dlsym failed: %s", errMsg); } dlclose(libHandle); // 使用完记得关闭库句柄 } else { const char *errMsg = dlerror(); NSLog(@"dlopen failed: %s", errMsg); }
4. 确保动态库正确嵌入App
在Xcode项目中,将libSum.dylib添加到Target -> General -> Embedded Binaries中,确保库被正确打包到App沙盒内,否则dlopen会找不到库文件。
内容的提问来源于stack exchange,提问作者Jackman3016
相关产品推荐
相关产品推荐

