在 Python 中加载 C 库会打开另一个 C 库 - 未解析的共享符号

Loading C library in Python that dlopens another C library - unresolved shared symbol

我有一个具有多种功能的商业 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 但 returns 未定义的符号。

//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')

returns错误代码:未定义符号:aglobal

一些其他注意事项:

是 Python 以不同方式绑定符号还是什么?

加载a.so时需要使用RTLD_GLOBAL

The object's symbols shall be made available for the relocation processing of any other object. In addition, symbol lookup using dlopen(0, mode) and an associated dlsym() allows objects loaded with this mode to be searched.

Linux man page更直白一点:

The symbols defined by this shared object will be made available for symbol resolution of subsequently loaded shared objects.

python documentation 描述了选项的存在,但没有描述它的作用。

New in version 2.6: The use_last_error and use_errno optional parameters were added.

ctypes.RTLD_GLOBAL
Flag to use as mode parameter. On platforms where this flag is not available, it is defined as the integer zero.

ctypes.RTLD_LOCAL
Flag to use as mode parameter. On platforms where this is not available, it is the same as RTLD_GLOBAL.

ctypes.DEFAULT_MODE
The default mode which is used to load shared libraries. On OSX 10.3, this is RTLD_GLOBAL, otherwise it is the same as RTLD_LOCAL.

根据文档,您所处的系统似乎 DEFAULT_MODERTLD_LOCAL 相同,这与 RTLD_GLOBAL 相反。