我有一个商业c库(a.so),它具有多个功能。当您调用a.open()函数时,它将动态地对另一个库执行dlopen()调用。如果调用a.open('b'),它将打开b.so。如果调用a.open('c'),它将打开c.so。
问题是a.so和b.so共享一个在a.so中定义的全局变量,但被b.so(和c.so等)引用。我能够使用ctypes在python中正确加载a.so并查看Python中的所有符号。但是,当我调用a.open('b')时,它将尝试加载b.so但返回未定义的符号。
//a.c -source for a.so library
int aglobal = 0;
void open(char* lib)
{ dlopen(lib); }
//b.c - source for b.so library
extern int aglobal;
这是我要加载的python代码:
from ctypes import cdll
p = ctypes.CDLL('a.so')
p.open('b')
返回错误代码:未定义的符号:aglobal
其他一些注意事项:
文件与-fPIC -rdynamic -shared
当我编写一个与python程序相同的C程序时, 没问题。
我还尝试了swig来包装库以及其他许多东西,构建选项等,但是结果相同。
Python是否以不同的方式绑定符号?
答案 0 :(得分:2)
加载a.so
时需要使用RTLD_GLOBAL
。
该对象的符号应可用于任何其他对象的重定位处理。此外,使用
dlopen(0, mode)
和关联的dlsym()
进行符号查找允许搜索以这种模式加载的对象。
Linux man page更加简单:
将创建此共享库定义的符号 可用于后续加载共享的符号解析 对象。
python documentation描述了选项的存在,但没有描述其作用。
2.6版中的新增功能:添加了use_last_error和use_errno可选参数。
ctypes.RTLD_GLOBAL
标记用作模式参数。在此标志不可用的平台上,它定义为整数零。
ctypes.RTLD_LOCAL
标记用作模式参数。在不可用的平台上,它与RTLD_GLOBAL
相同。
ctypes.DEFAULT_MODE
用于加载共享库的默认模式。在OSX 10.3上,该值为RTLD_GLOBAL
,否则与RTLD_LOCAL
相同。
从文档中可以看出,您所处的系统上DEFAULT_MODE
与RTLD_LOCAL
相同,这与RTLD_GLOBAL
相反。