Pregunta

¿Cómo se actualiza esta variable de entorno en tiempo de ejecución para que ctypes pueden cargar una biblioteca donde quiera? He intentado lo siguiente y ninguno parece funcionar.

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

Solución

En el momento en un programa como Python está en funcionamiento, el cargador dinámico (ld.so.1 o algo similar) ha leído ya LD_LIBRARY_PATH y no note ningún cambio a partir de entonces. Por lo tanto, a menos que el software Python misma se evalúa LD_LIBRARY_PATH y lo utiliza para construir el posible nombre de la ruta de la biblioteca para dlopen() o una función equivalente a utilizar, el establecimiento de la variable en la secuencia de comandos no tendrá ningún efecto.

Teniendo en cuenta que usted dice que no funciona, parece plausible suponer que Python no construye y tratar todos los posibles nombres de biblioteca; es probable que se basa en LD_LIBRARY_PATH solo.

Otros consejos

Incluso si se le da una ruta de acceso completa a CDLL o cdll.LoadLibrary (), es posible que tenga que configurar LD_LIBRARY_PATH antes de invocar Python. Si la biblioteca compartida se carga de forma explícita se refiere a otra biblioteca compartida y no "rpath" se establece en el .so para esa biblioteca, entonces no va a encontrar, incluso si ya se ha cargado. Un rpath en una biblioteca especifica una ruta de búsqueda que se utiliza para buscar otras bibliotecas que necesita esa biblioteca

Por ejemplo, tengo un caso de un conjunto de bibliotecas de terceros interdependientes no producidos por mí. b.so referencias a.so. Incluso si me carga a.so con antelación:

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

Me aparece un error en la segunda carga, porque b.so se refiere a simplemente 'a.so', sin un rpath, y así b.so no sabe que es la correcta a.so. Así que tengo que fijar de antemano LD_LIBRARY_PATH para incluir '/ abs / ruta / a'.

Para evitar tener que configurar LD_LIBRARY_PATH, que modifica la entrada rpath en los archivos .so. En Linux, hay dos utilidades que he encontrado que hacer esto: chrpath y patchelf . chrpath está disponible en los repositorios de Ubuntu. No puede cambiar el rpath de .so que nunca han tenido uno. patchelf es más flexible.

CDLL se puede pasar un nombre de ruta completo, así que por ejemplo estoy usando el siguiente en uno de mis guiones donde el .so se encuentra en el mismo directorio que el script en Python.

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

En el caso de que el siguiente debería ser suficiente.

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

Compilar su binario con un rpath relativa al directorio de trabajo actual como:

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

A continuación, usted es capaz de cambiar el directorio de trabajo en Python en tiempo de ejecución:

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

De esta manera, el cargador se encuentran también otras bibliotecas dinámicas como otherbinary.so

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top