简体   繁体   中英

ctypes loading a c shared library that has dependencies

On Linux, I have ac 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 ao bo co ) 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.

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)

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.

Based on Walter Nissen's answer above, you can modify the code to be:

import os
ctypes.CDLL(libidcwf_path, mode=os.RTLD_LAZY)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM