Изменение LD_LIBRARY_PATH во время выполнения для ctypes

StackOverflow https://stackoverflow.com/questions/856116

  •  21-08-2019
  •  | 
  •  

Вопрос

Как вы обновляете эту переменную среды во время выполнения, чтобы ctypes могли загружать библиотеку где угодно?Я пробовал следующее, но, похоже, ни то, ни другое не сработало.

from ctypes import *
os.environ['LD_LIBRARY_PATH'] = "/home/starlon/Projects/pyCFA635/lib"  
os.putenv('LD_LIBRARY_PATH', "/home/starlon/Projects/pyCFA635/lib")  
lib = CDLL("libevaluator.so")
Это было полезно?

Решение

К моменту запуска такой программы, как Python, динамический загрузчик (ld.so.1 или что-то подобное) уже прочитал LD_LIBRARY_PATH и после этого не заметит никаких изменений.Итак, если только само программное обеспечение Python не вычисляет LD_LIBRARY_PATH и не использует его для построения возможного имени пути библиотеки для dlopen() или эквивалентную функцию для использования, установка переменной в скрипте не будет иметь никакого эффекта.

Учитывая, что вы говорите, что это не работает, кажется правдоподобным предположить, что Python не создает и не пробует все возможные имена библиотек;вероятно, он полагается только на LD_LIBRARY_PATH .

Другие советы

Даже если вы укажете полный путь к CDLL или cdll.LoadLibrary(), вам все равно может потребоваться установить LD_LIBRARY_PATH перед вызовом Python.Если загружаемая вами общая библиотека явно ссылается на другую общую библиотеку и в файле .so для этой библиотеки не задан "rpath", то она не будет найдена, даже если она уже была загружена.rpath в библиотеке указывает путь поиска, который будет использоваться для поиска других библиотек, необходимых этой библиотеке

Например, у меня есть случай набора взаимозависимых сторонних библиотек, созданных не мной.b.so ссылки a.so .Даже если я загружу a.so заранее:

ctypes.cdll.LoadLibrary('/abs/path/to/a.so')
ctypes.cdll.LoadLibrary('/abs/path/to/b.so')

Я получаю ошибку при второй загрузке, потому что b.so ссылается просто на 'a.so', без rpath , и поэтому b.so не знает, что это правильно a.so.Поэтому я должен заранее установить LD_LIBRARY_PATH, чтобы включить '/abs/path/to'.

Чтобы избежать необходимости задавать LD_LIBRARY_PATH, вы изменяете запись rpath в файлах .so.В Linux есть две утилиты, которые я нашел, которые делают это:chrpath, и нашивка.chrpath доступен из репозиториев Ubuntu.Он не может изменить rpath на .so, у которого его никогда не было.patchelf более гибкий.

CDLL может быть передан полный путь, поэтому, например, я использую следующее в одном из моих сценариев, где .so находится в том же каталоге, что и скрипт python.

import os
path = os.path.dirname(os.path.realpath(__file__))
dll = CDLL("%s/iface.so"%path)

В вашем случае должно быть достаточно следующего.

from ctypes import *
lib = CDLL("/home/starlon/Projects/pyCFA635/lib/libevaluator.so")

Скомпилируйте ваш двоичный файл с rpath относительно текущего рабочего каталога, например:

gcc -shared -o yourbinary.so yoursource.c otherbinary.so \
    -Wl,-rpath='.',-rpath='./another/relative/rpath' -fpic

Затем вы сможете изменить рабочий каталог в python во время выполнения с помощью:

import os
os.chdir('/path/to/your/binaries')

Подобным образом загрузчик также находит другие динамические библиотеки, такие как otherbinary.so

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top