Доступ к библиотеке, скомпилированной без -fPIC, из python

У меня есть библиотека x86_64 с закрытым исходным кодом, к которой я хочу получить доступ из Python в Linux.

Я обычно использую для этого ctypes.

Но эта библиотека поставляется в виде файла архива (* .a). Я не могу повторно связать библиотеку с динамическим * .so, потому что она была скомпилирована без опции -fPIC. ctypes нужна * .so dll.

Могу ли я, помимо жалобы упаковщикам этой библиотеки, поместить ее в * .so? Может, как-нибудь написать обёрточные функции?

Редактировать:

Попытка ответить на вопрос https://stackoverflow.com/a/2657390/4323:

gcc -shared -o closed_lib.so -Wl,--whole-archive -fPIC closed_lib.a -Wl,--no-whole-archive
/usr/bin/ld: closed_lib.a(myFFT.o): relocation R_X86_64_32S against `.bss' can not be used when making a shared object; recompile with -fPIC
closed_lib.a(myFFT.o): error adding symbols: Bad value
collect2: error: ld returned 1 exit status
make: *** [closed_lib.so] Error 1

person markrages    schedule 23.10.2014    source источник
comment
Вы можете попробовать это: stackoverflow.com/a/2657390/4323, но есть комментарий, в котором говорится, что это может не работать на 64- бит Linux.   -  person John Zwinck    schedule 23.10.2014
comment
@JohnZwinck Ага, не работает на x86_64.   -  person markrages    schedule 23.10.2014


Ответы (1)


Я заставил его работать для базового случая, но похоже, что вы обнаружили то же решение примерно в то же время, но оно не сработало для вас. Я все равно опишу, что сделал.

Сначала создайте файл static.c, содержащий некоторый код C (пропустите это, если у вас уже есть статическая библиотека):

int foo(int x) {
  return x * 2;
}

Сделайте статическую библиотеку:

gcc -g -o static.o -c static.c
ar -rv libstatic.a static.o

Теперь у нас есть статическая библиотека, зависящая от позиции. Сделаем общую библиотеку!

gcc -g -shared -o libshared.so -Wl,--whole-archive -L. -lstatic -Wl,--no-whole-archive

И, наконец, протестируем его с помощью Python:

import ctypes
print ctypes.cdll.LoadLibrary('./libshared.so').foo(42)

Это дает ожидаемый 84.

Я позаимствовал подход из другого ответа, здесь: https://stackoverflow.com/a/10963770/4323


Согласно этому: https://stackoverflow.com/a/19768349/4323 может быть невозможно делать то, что вы пытаемся сделать. Возможно, вам действительно нужно перестроить статическую библиотеку. Или, может быть, вы можете отредактировать символы, которые вызывают у вас проблемы, если они вам не нужны? У вас есть список символов, которые вам действительно нужны?


Если ничего из вышеперечисленного не помогает, совершенно иным подходом будет создание исполняемой программы, связанной с вашей статической библиотекой, и выполнение чего-то вроде RPC для запуска кода в этом процессе как службы.


Старый ответ, похоже, применим только к Solaris:

Отсюда: Связывание общей библиотеки со статической библиотекой: должна ли статическая библиотека компилироваться иначе, чем если бы приложение связывало ее? Кажется, вам нужно добавить опцию -mimpure-text при создании разделяемой библиотеки из статической библиотеки, отличной от PIC.

person John Zwinck    schedule 23.10.2014
comment
Согласно man gcc, -mimpure-text поддерживается только в Solaris 2. - person markrages; 23.10.2014
comment
@markrages: верно. Я сильно переработал свой ответ. Возможно, у вас останутся менее элегантные варианты, но есть несколько вещей, которые следует учесть выше. - person John Zwinck; 23.10.2014