我有一组库要作为在ubuntu派生的ARM linux 64位上的API(关闭源)的一部分加载。 我需要使用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.LoadLibrary的这个CDLL? 我无法定义加载它们的顺序。
是否存在某种“惰性” .so加载? 还是可以避免符号检查?
我发现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
有没有一种方法可以绕过这个并强制加载两个库?
答案 0 :(得分:0)
好吧,也许我在这里找到了解决问题的灵感:
https://stackoverflow.com/a/53343430/76081
只需将RTLD_LAZY标志定义为1,并与RTLD_GLOBAL一起使用 TOGETHER 。
因此,代码变为:
from ctypes import *
RTLD_LAZY = 0x0001
LAZYLOAD= RTLD_LAZY | RTLD_GLOBAL
...
libubx=CDLL("libubx.so",mode= LAZYLOAD)
libpos=CDLL("libpos.so",mode= LAZYLOAD)
....
现在它不引发任何异常