ctypes加载具有依赖项的c共享库

时间:2010-02-24 15:53:22

标签: python linux ctypes

在Linux上,我有一个依赖于其他库的c共享库。正确设置LD_LIBRARY_PATH以允许链接器加载所有库。当我这样做时:

libgidcwf    = ctypes.cdll.LoadLibrary(libidcwf_path)

我收到以下错误:

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

似乎LD_LIBRARY_PATH在这里没有效果。 有没有办法让这些依赖库“可加载”?

提前感谢您的帮助。

6 个答案:

答案 0 :(得分:17)

似乎libwav.so没有声明它对定义ODBCGeneralQuery的库的依赖性。尝试运行ldd path-to-my-lib/libwav.so并查看是否缺少某些内容。如果这是您正在构建的共享库,则应将-llibname添加到库代码使用的每个库的链接命令(类似gcc -shared -o libwav.so a.o b.o c.o的命令)中。原始共享库以这种方式引用的任何其他库也应自动加载。

答案 1 :(得分:6)

您应该使用RTLD_GLOBAL。我有一个混合平台系统,所以我的代码看起来像这样:

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)

答案 2 :(得分:6)

编译共享对象时,请务必将所有-lsomething放在string命令的末尾。对我来说,它解决了这个问题。

答案 3 :(得分:4)

我遇到了同样的问题。 为了解决这个问题,需要做两件事:

  1. 像其他用户所说的那样使用RTLD_GLOBAL
  2. 您需要加载库使用的每个库。因此,如果在ODBCGeneralQuery中定义libIDCodbc,则需要先运行此行:
  3. ctypes.CDLL("libIDCodbc.so", mode = ctypes.RTLD_GLOBAL)

答案 4 :(得分:3)

我发现我必须使用RTLD_LAZY,因为未链接的未定义符号,因为它没有被使用。由于我的ctypes中没有ctypes.RTLD_LAZY,我不得不使用:

ctypes.CDLL(libidcwf_path, mode=1)

我通过检查/usr/include/bits/dlfcn.h找到了这种模式,这可能不是标准的。在ctypes邮件列表上提示2006年thread

答案 5 :(得分:1)

基于上述Walter Nissen的answer,您可以将代码修改为:

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