我有一组库作为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
有没有办法绕过这个并强制加载两个库?
好吧,我可能在这里找到了解决问题的灵感:
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)
....
现在它没有例外