Подтвердить что ты не робот

Ctypes загружает c общую библиотеку с зависимостями

В 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 здесь не действует. Есть ли способ, чтобы библиотека зависимостей "загружалась"?

Заранее благодарим за помощь.

4b9b3361

Ответ 1

Казалось бы, libwav.so не объявляет его зависимость от библиотеки, определяющей ODBCGeneralQuery. Попробуйте запустить ldd path-to-my-lib/libwav.so и посмотрите, нет ли чего-то. Если это общая библиотека, которую вы строите, вы должны добавить -llibname к команде связывания (той, которая похожа на gcc -shared -o libwav.so a.o b.o c.o) для каждой библиотеки, используемой в библиотечном коде. Любые другие библиотеки, на которые ссылается исходная разделяемая библиотека таким образом, также должны автоматически загружаться.

Ответ 2

Вы должны использовать 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)

Ответ 3

При компиляции общего объекта обязательно поставьте все -lsomething в конце строки. Для меня это решило проблему.

Ответ 4

У меня была та же проблема. Для его решения потребовались две вещи:

  • используйте RTLD_GLOBAL, как говорят другие пользователи.
  • Вам нужно загрузить каждую библиотеку, используемую вашей библиотекой. Так что если ODBCGeneralQuery определено в let say libIDCodbc, вам нужно сначала запустить эту строку:

ctypes.CDLL("libIDCodbc.so", mode = ctypes.RTLD_GLOBAL)

Ответ 5

Я обнаружил, что мне пришлось использовать RTLD_LAZY из-за символа undefined, который не был связан, потому что он не использовался. Поскольку в моих типах нет ctypes.RTLD_LAZY, мне пришлось использовать:

ctypes.CDLL(libidcwf_path, mode=1)

Я нашел этот режим, проверив /usr/include/bits/dlfcn.h, который, вероятно, не является стандартным. Перейти к этой теме thread в списке рассылки ctypes.

Ответ 6

Основываясь на ответе Вальтера Ниссена выше, вы можете изменить код так:

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