Python загружает C lib с CDLL, не видит библиотеки в пути Python - PullRequest
7 голосов
/ 04 февраля 2012

Я пытаюсь заставить работать какой-нибудь академический код с открытым исходным кодом (дом проекта здесь ). Это большая кодовая база C ++ с (очень) тонкой оболочкой Python, которая использует CDLL для загрузки C ++ и вызова некоторых функций C, которые позволяют примитивному написанию сценариев Python для кода.

Однако исходный код импорта падает, потому что он не может найти .so файлы, сидящие рядом с ним в пакетах сайта:

в установленном файле:

from ctypes import *

try:
  self.lib = CDLL("_lammps.so")
except:
  try:
    self.lib = CDLL("_lammps_serial.so")
  except:
    raise OSError,"Could not load LAMMPS dynamic library"

и в скрипте или интерпретаторе:

from lammps import lammps
l = lammps()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "lammps.py", line 42, in __init__
    raise OSError,"Could not load LAMMPS dynamic library"
OSError: Could not load LAMMPS dynamic library

Другие ответы может показаться, что это покрыто , но это работает только в том случае, если CDLL() вызывается внутри фактически вызванного скрипта (или рабочего каталога приглашения, запустившего интерпретатор) - то есть, если 'относительный путь' находится в пространстве пользователя, а не в пространстве библиотеки Python.

Как мы можем надежно установить для импорта библиотеку C / C ++, которую мы создали сами? Если не считать загрязнение мест расположения системных библиотек, таких как /usr/lib, что не очень питонично, я не вижу простого решения.

(РЕДАКТИРОВАТЬ: исправлены имена функций, неясный рефакторинг, бесполезен! Извините!)

Ответы [ 4 ]

3 голосов
/ 02 июля 2017

Я нахожусь на Linux, все, что я сделал, чтобы исправить эту проблему, было помещено в абсолютный путь от модуля OS, и он работает

from ctypes import *
import os

xss = cdll.LoadLibrary(os.path.abspath("libxss.so.1"))
print xss.xss_test_1()

Это и Python 2.7.

1 голос
/ 07 мая 2013

Вы можете использовать переменную __file__ в пакете, который выполняет импорт.Просто используйте различные функции os.path, чтобы извлечь полный, абсолютный путь к каталогу из __file__, а затем присоедините его к имени вашей библиотеки.Что-то вроде:

temp = os.path.abspath(__file__)
temp = os.path.realpath(temp)
temp = os.path.dirname(temp)
temp = os.path.join(temp, "_lammps.so")
lib = CDLL(path)

Вы также можете попробовать различные варианты вашего основного имени файла (например, с .dll или .dylib вместо .so, с префиксом lib и бези, возможно, даже с добавленными номерами версий), если вы хотите быть независимым от платформы, и ваша система сборки может производить такие вещи.Затем вы можете либо попробовать несколько версий, либо просто использовать glob.glob, чтобы помочь вам найти приемлемую.

Я должен сказать, что странно, что в стандартной библиотеке такой функции не существует.ctypes.util.find_library недостаточно гибок (или тщателен) для такого использования (которое, я думаю, было широко распространено).Даже просто функция, которая искала файл через PYTHONPATH, была бы весьма полезна (хотя ее не сложно написать).

Опять же, кажется, что если вы просто добавите правильный каталог в LD_LIBRARY_PATH,Вы должны быть в состоянии загрузить его .

1 голос
/ 06 февраля 2012

Запустите под strace -eopen, вы увидите что-то вроде этого:

open("tls/x86_64/_lammps.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("tls/_lammps.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("x86_64/_lammps.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("_lammps.so", O_RDONLY|O_CLOEXEC)  = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6
open("/lib/_lammps.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/_lammps.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

Который показывает вам все места, где Python ctypes ищет вашу библиотеку. До сих пор мне не удалось найти подстройку переменной среды выполнения, позволяющую добавлять местоположения поиска в моей системе, возможно, вам придется использовать абсолютные пути.

0 голосов
/ 25 июня 2018

Вы должны указать абсолютный путь.Попробуйте следующее:

import os
from ctypes import *

try:
  slib = os.getcwd() + '/' +'_lammps.so'
  hlibc = CDLL(slib)
  hilbc.FunctionName()
except:
  try:
    slib = os.getcwd() + '/' +'_lammps_serial.so'
    hlibc = CDLL(slib)
  except:
    raise OSError,"Could not load LAMMPS dynamic library"
...