python 2.7 ctypes:.so共享库的循环依赖项

问题描述 投票:0回答:1

我有一组库作为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

[email protected]:~/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

[email protected]:~/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.LoadLibrary的这个机智CDLL?我无法定义加载它们的订单。

有没有一种“懒惰”.so loading?或者是否可以避免符号检查?

我发现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

有没有办法绕过这个并强制加载两个库?

python shared-libraries embedded-linux ctypes circular-dependency
1个回答
0
投票

好吧,我可能在这里找到了解决问题的灵感:

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)
....

现在它没有例外

© www.soinside.com 2019 - 2024. All rights reserved.