Pergunta

Como você atualizar esta variável de ambiente em tempo de execução para que os ctypes pode carregar uma biblioteca onde quer? Eu tentei o seguinte e nem parece trabalho.

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")
Foi útil?

Solução

No momento em um programa como o Python está em execução, o carregador dinâmico (ld.so.1 ou algo similar) já tenha lido LD_LIBRARY_PATH e não notar qualquer alteração posterior. Então, a menos que o software Python em si avalia LD_LIBRARY_PATH e usa-lo para construir o possível nome do caminho da biblioteca para dlopen() ou uma função equivalente à utilização, definindo a variável no script não terá nenhum efeito.

Uma vez que você diz que não funciona, parece plausível supor que o Python não construir e experimentar todos os possíveis nomes de biblioteca; ele provavelmente depende sozinho LD_LIBRARY_PATH.

Outras dicas

Mesmo se você dá um caminho totalmente qualificado para CDLL ou cdll.LoadLibrary (), você pode ainda precisa definir LD_LIBRARY_PATH antes de invocar Python. Se a biblioteca compartilhada você carregar explicitamente refere-se a uma outra biblioteca compartilhada e não "rpath" está situado no .so para essa biblioteca, então ele não vai ser encontrado, mesmo que já tenha sido carregado. Um rpath em uma especifica biblioteca um caminho de pesquisa a ser usado para procurar outras bibliotecas necessárias para que a biblioteca

Por exemplo, eu tenho um caso de um conjunto de bibliotecas interdependentes de terceiros não produzidos por mim. b.so referências a.so. Mesmo se eu carregar a.so com antecedência:

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

Eu recebo um erro no segundo carga, porque b.so refere-se simplesmente 'a.so', sem uma rpath, e assim b.so não sabe que é o a.so. correta Então eu tenho que definir LD_LIBRARY_PATH com antecedência para incluir '/ abs / path / to'.

Para evitar ter de set LD_LIBRARY_PATH, você modificar a entrada rpath nos arquivos .so. No Linux, há dois utilitários que achei que fazer isso: chrpath e patchelf . chrpath está disponível nos repositórios do Ubuntu. Ela não pode mudar rpath em .so é que nunca teve um. patchelf é mais flexível.

CDLL pode ser passado um nome de caminho totalmente qualificado, por isso, por exemplo, eu estou usando o seguinte em um dos meus scripts onde o .so está no mesmo diretório que o script python.

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

No seu caso o seguinte deve ser suficiente.

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

Compilar o binário com um rpath relativo ao diretório de trabalho atual como:

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

Em seguida, você é capaz de mudar o diretório de trabalho em python em tempo de execução com:

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

Assim, o carregador também encontra outras bibliotecas dinâmicas como otherbinary.so

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top