python - windll - c_int()
Cambiando LD_LIBRARY_PATH en tiempo de ejecuciĆ³n para ctypes (4)
¿Cómo se actualiza esta variable de entorno en tiempo de ejecución para que ctypes pueda cargar una biblioteca en cualquier lugar? Intenté 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")
A CDLL se le puede pasar un nombre de ruta completo, así que, por ejemplo, estoy usando lo siguiente en uno de mis scripts donde el .so está en el mismo directorio que el script de python.
import os
path = os.path.dirname(os.path.realpath(__file__))
dll = CDLL("%s/iface.so"%path)
En tu caso, lo siguiente debería ser suficiente.
from ctypes import *
lib = CDLL("/home/starlon/Projects/pyCFA635/lib/libevaluator.so")
Compila tu binario con un rpath relativo al directorio de trabajo actual como:
gcc -shared -o yourbinary.so yoursource.c otherbinary.so /
-Wl,-rpath=''.'',-rpath=''./another/relative/rpath'' -fpic
Luego, puede cambiar el directorio de trabajo en python en tiempo de ejecución con:
import os
os.chdir(''/path/to/your/binaries'')
De esta manera, el cargador también encuentra otras bibliotecas dinámicas como otherbinary.so
Incluso si proporciona una ruta de acceso totalmente calificada a CDLL o cdll.LoadLibrary (), es posible que aún necesite establecer LD_LIBRARY_PATH antes de invocar Python. Si la biblioteca compartida que carga explícitamente hace referencia a otra biblioteca compartida y no se establece "rpath" en .so para esa biblioteca, no se encontrará, incluso si ya se ha cargado. Un rpath en una biblioteca especifica una ruta de búsqueda que se utilizará para buscar otras bibliotecas necesarias para esa biblioteca
Por ejemplo, tengo un caso de un conjunto de bibliotecas de terceros interdependientes que no he creado. b.so hace referencia a.so. Incluso si cargo a.so de antemano:
ctypes.cdll.LoadLibrary(''/abs/path/to/a.so'')
ctypes.cdll.LoadLibrary(''/abs/path/to/b.so'')
Recibo un error en la segunda carga, porque b.so se refiere simplemente a ''a.so'', sin un rpath, y por eso b.so no sabe que es el correcto a.so. Así que tengo que establecer LD_LIBRARY_PATH de antemano para incluir ''/ abs / path / to''.
Para evitar tener que establecer LD_LIBRARY_PATH, modifique la entrada rpath en los archivos .so. En Linux, hay dos utilidades que encontré que hacen esto: chrpath y patchelf . Chrpath está disponible en los repositorios de Ubuntu. No puede cambiar rpath en .so que nunca tuvo uno. patchelf es más flexible.
Para cuando se ejecuta un programa como Python, el cargador dinámico (ld.so.1 o algo similar) ya ha leído LD_LIBRARY_PATH y no notará ningún cambio a partir de ese momento. Entonces, a menos que el software Python mismo evalúe LD_LIBRARY_PATH y lo use para construir el posible nombre de ruta de la biblioteca para dlopen()
o una función equivalente a usar, establecer la variable en el script no tendrá efecto.
Dado que usted dice que no funciona, parece plausible suponer que Python no compila y prueba todos los nombres de biblioteca posibles; probablemente solo confía en LD_LIBRARY_PATH.