Python 2.7 ctypes: циклические зависимости разделяемых библиотек .so - PullRequest
0 голосов
/ 17 апреля 2019

У меня есть набор библиотек для загрузки как часть API (с закрытым исходным кодом) на ARM linux 64bit, производного от Ubuntu. Мне нужно взаимодействовать с этими библиотеками, используя скрипт Python (на данный момент 2.7), поэтому я использую ctypes Перед последним выпуском я смог загрузить все без проблем после того, как нашел правильный порядок загрузки. Однако в последнем выпуске они создали две библиотеки, libpos.so и libubx, с взаимозависимостью. Фактически, когда я пытаюсь загрузить эти библиотеки, я получаю:

libubx=CDLL("libubx.so", mode = RTLD_GLOBAL)
libpos=CDLL("libpos.so", mode = RTLD_GLOBAL)

Я получаю

Traceback (most recent call last):
  File "testloading.py", line 11, in <module>
    libubx=CDLL("libubx.so", mode = RTLD_GLOBAL)
  File "/usr/lib/python2.7/ctypes/__init__.py", line 362, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: ./v2x-lib/lib/mk5/libubx.so: undefined symbol: GPSRX_UpdatePosition

переключение порядка загрузки как:

libpos=CDLL("libpos.so", mode = RTLD_GLOBAL)
libubx=CDLL("libubx.so", mode = RTLD_GLOBAL)

я получаю

Traceback (most recent call last):
  File "testloading.py", line 11, in <module>
    libpos=CDLL("libpos.so", mode = RTLD_GLOBAL)
  File "/usr/lib/python2.7/ctypes/__init__.py", line 362, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: ./v2x-lib/lib/mk5/libpos.so: undefined symbol: UBX8_ProcessUbxPacket

проверка с помощью nm для GPSRX_UpdatePosition

duser@10.233.1.70:~/mk5$ nm ./stack/v2x-lib/lib/mk5/*.so | grep "\.so\|GPSRX_UpdatePosition"
...
./stack/v2x-lib/lib/mk5/libpos.so:
000025a5 T GPSRX_UpdatePosition
...
./stack/v2x-lib/lib/mk5/libubx.so:
         U GPSRX_UpdatePosition
...

и для UBX8_ProcessUbxPacket

duser@10.233.1.70:~/mk5$ nm ./stack/v2x-lib/lib/mk5/*.so | grep "\.so\|UBX8_ProcessUbxPacket"
...
./stack/v2x-lib/lib/mk5/libpos.so:
         U UBX8_ProcessUbxPacket
...
./stack/v2x-lib/lib/mk5/libubx.so:
00003801 T UBX8_ProcessUbxPacket
...

Как видите, существует циклическая / взаимозависимость. Как можно управлять этим остроумием CDLL cdll.LoadLibrary? Я не могу определить порядок их загрузки.

Есть ли что-то вроде "ленивых" .со такой загрузкой? Или можно избежать проверки символа?

Я обнаружил, что RTLD_GLOBAL и RTLD_LOCAL определены только в ctypes, без RTLD_LAZY. в любом случае, заставляя

libubx=CDLL("libubx.so", mode = 1)

идет нормально, без ошибок (поэтому я полагаю, что UBX8_ProcessUbxPacket должен быть определен). Но, когда сразу после того, как я пытаюсь загрузить libpos

libpos=CDLL("libpos.so", mode = RTLD_GLOBAL)

или также

libpos=CDLL("libpos.so", mode = 1)

Я все еще получаю ошибку:

Traceback (most recent call last):
  File "testloading.py", line 12, in <module>
    libpos=CDLL("libpos.so", mode = 1)
  File "/usr/lib/python2.7/ctypes/__init__.py", line 362, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: ./v2x-lib/lib/mk5/libpos.so: undefined symbol: UBX8_ProcessUbxPacket

Есть ли способ обойти это и принудительно загрузить обе библиотеки?

1 Ответ

0 голосов
/ 17 апреля 2019

Хорошо, возможно, я нашел вдохновение для решения этой проблемы:

https://stackoverflow.com/a/53343430/76081

Просто определите флаг RTLD_LAZY как 1 и используйте его ВМЕСТЕ сRTLD_GLOBAL.

Таким образом, код становится примерно таким:

from ctypes import *

RTLD_LAZY = 0x0001

LAZYLOAD= RTLD_LAZY | RTLD_GLOBAL


...
libubx=CDLL("libubx.so",mode= LAZYLOAD)
libpos=CDLL("libpos.so",mode= LAZYLOAD)
....

и теперь он не вызывает исключений

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...