Reputation: 1727
I've a set of libraries to load as part of an API (close source) on a ARM linux 64bit, ubuntu derived. I need to interact with this libraries using a python script (2.7 for the moment) so I'm using ctypes. Before the last release, I was able to load all the so without problems after I found the correct loading order. In the last release, however, they have build up two libraries, libpos.so and libubx, with a mutual dependency. Infact, when I try to load these libraries I get:
libubx=CDLL("libubx.so", mode = RTLD_GLOBAL)
libpos=CDLL("libpos.so", mode = RTLD_GLOBAL)
I get
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
switching the loading order as:
libpos=CDLL("libpos.so", mode = RTLD_GLOBAL)
libubx=CDLL("libubx.so", mode = RTLD_GLOBAL)
i get
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
inspecting with nm for 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
...
and for the 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
...
As you see, there is a cyclical/mutual dependency. How can manage this wit CDLL of cdll.LoadLibrary ? I cannot define an order to load them.
Is there a sort of "lazy" .so loading ? Or is it possible to avoid the symbol checking?
I found that RTLD_GLOBAL, and RTLD_LOCAL only are defined in ctypes, no RTLD_LAZY. anyway, forcing
libubx=CDLL("libubx.so", mode = 1)
is going fine without errors ( so i suppose the UBX8_ProcessUbxPacket should be defined). But, when immediately after i try to load the libpos
libpos=CDLL("libpos.so", mode = RTLD_GLOBAL)
or also
libpos=CDLL("libpos.so", mode = 1)
I'm still getting the error:
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
Is there a way to bypass this and force the loading of both libraries ?
Upvotes: 1
Views: 624
Reputation: 1727
Ok, probably I found an inspiration to solve the problem here:
https://stackoverflow.com/a/53343430/76081
Simply define the RTLD_LAZY flag as 1 and the use it TOGETHER with RTLD_GLOBAL.
So the code becomes something like:
from ctypes import *
RTLD_LAZY = 0x0001
LAZYLOAD= RTLD_LAZY | RTLD_GLOBAL
...
libubx=CDLL("libubx.so",mode= LAZYLOAD)
libpos=CDLL("libpos.so",mode= LAZYLOAD)
....
and now it raises no exceptions
Upvotes: 2