ctypes loading a c shared library that has dependencies
On Linux, I have a c shared library that depends on other libs. LD_LIBRARY_PATH is properly set to allow the linker to load all the libraries. When I do:
libgidcwf =开发者_开发问答 ctypes.cdll.LoadLibrary(libidcwf_path)
I get the following error:
Traceback (most recent call last):
File "libwfm_test.py", line 12, in <module>
libgidcwf = ctypes.cdll.LoadLibrary(libidcwf_path)
File "/usr/lib/python2.5/ctypes/__init__.py", line 431, in LoadLibrary
return self._dlltype(name)
File "/usr/lib/python2.5/ctypes/__init__.py", line 348, in __init__
self._handle = _dlopen(self._name, mode)
OSError: path-to-my-lib/libwav.so: undefined symbol: ODBCGeneralQuery
It seems that LD_LIBRARY_PATH
has no effect here.
Is there a way to have these dependency library "loadable"?
Thanks in advance for the help.
It would seem that libwav.so does not declare it's dependency on the library defining ODBCGeneralQuery. Try running ldd path-to-my-lib/libwav.so
and see if there's something missing. If this is a shared library that you are building you should add -llibname
to the linking command (the one that is something like gcc -shared -o libwav.so a.o b.o c.o
) for each library that the library's code uses. Any other libraries referenced by the original shared library in this way should automatically be loaded as well.
I found I had to use RTLD_LAZY
due to an undefined symbol that was not linked because it was not being used. Since there is no ctypes.RTLD_LAZY
in my ctypes, I had to use:
ctypes.CDLL(libidcwf_path, mode=1)
I found this mode by inspecting /usr/include/bits/dlfcn.h
which is probably not standard. Hat tip to this 2006 thread on the ctypes mailing list.
You should use RTLD_GLOBAL. I have a mixed platform system, so my code looks something like this:
import numpy, ctypes
try:
if "Linux" in esmfos:
_ESMF = ctypes.CDLL(libsdir+'/libesmf.so', mode=ctypes.RTLD_GLOBAL)
else:
_ESMF = numpy.ctypeslib.load_library('libesmf', libsdir)
except:
traceback.print_exc(file=sys.stdout)
sys.exit(ESMP_ERROR_SHAREDLIB)
When you compile the shared object, be sure to put all the -lsomething
at the end of the string command. For me it solved the problem.
I had the same problem. Two things were required in order to solve it:
- use the
RTLD_GLOBAL
as other users said - You need to load every library that is used by your library. So if
ODBCGeneralQuery
is defined in lets saylibIDCodbc
, you need first run this line:
ctypes.CDLL("libIDCodbc.so", mode = ctypes.RTLD_GLOBAL)
Based on Walter Nissen's answer above, you can modify the code to be:
import os
ctypes.CDLL(libidcwf_path, mode=os.RTLD_LAZY)
精彩评论