У меня есть коммерческая библиотека 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 и т.д.). Я могу правильно загрузить a.so в python с помощью ctypes и увидеть все символы в 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')
возвращает код ошибки: undefined symbol: aglobal
Некоторые другие примечания:
файлы связаны с -fPIC -динамическим -shared
Когда я пишу программу на языке C, которая делает то же самое, что и программа python, проблема не возникает.
Я попробовал swig, чтобы обернуть библиотеку также, и множество других вещей, варианты сборки и т.д., Но такие же результаты.
Является ли Python привязкой символов по-другому или чем-то еще?
Вы должны использовать RTLD_GLOBAL
при загрузке a.so
.
Символы объекта должны быть доступны для обработки перемещения любого другого объекта. Кроме того, поиск символа с использованием
dlopen(0, mode)
и связанного с нимdlsym()
позволяет объектам, загруженным в этот режим, искать.
Персональная страница Linux немного более проста:
Символы, определенные этим общим объектом, будут доступны для разрешения символов впоследствии загруженных совместно используемых объектов.
Документация python описывает наличие опции, но не описывает, что она делает.
Новое в версии 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
.