开发者

ctypes loading a c shared library that has dependencies

开发者 https://www.devze.com 2022-12-20 23:03 出处:网络
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:

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:

  1. use the RTLD_GLOBAL as other users said
  2. You need to load every library that is used by your library. So if ODBCGeneralQuery is defined in lets say libIDCodbc, 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)
0

精彩评论

暂无评论...
验证码 换一张
取 消