Загрузка библиотеки C в Python, которая закрывает другую библиотеку C - неразрешенный общий символ

1

У меня есть коммерческая библиотека 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 привязкой символов по-другому или чем-то еще?

  • 0
    Хороший вопрос - это Ubuntu 18.04 и Python 3.6.
Теги:
ctypes
dlopen

1 ответ

2
Лучший ответ

Вы должны использовать 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.

  • 0
    Большое спасибо. Это было достаточно просто для вас! Я также обнаружил, что когда я использую свою SWIG-библиотеку, я могу сделать это, чтобы импортированная библиотека правильно добавила b.so. ссылка
  • 0
    При использовании языка сценариев для выполнения системного программирования помните, что иногда вам нужно будет обратиться к справочному материалу по операционной системе.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню