Domanda

Come si aggiorna questa variabile di ambiente in fase di esecuzione in modo che possano ctypes caricare una libreria ovunque? Ho provato quanto segue e non sembra funzionare.

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")
È stato utile?

Soluzione

Per il momento in un programma come Python è in esecuzione, il loader dinamico (ld.so.1 o qualcosa di simile) ha già letto LD_LIBRARY_PATH e non si noterà alcuna modifica in seguito. Quindi, a meno che il software Python stesso viene valutata LD_LIBRARY_PATH e lo utilizza per costruire il possibile nome del percorso della libreria per dlopen() o una funzione equivalente da usare, impostando la variabile nello script non avrà alcun effetto.

Dato che si dice che non funziona, sembra plausibile supporre che Python non costruisce e provare tutti i possibili nomi di libreria; probabilmente si basa su soli LD_LIBRARY_PATH.

Altri suggerimenti

Anche se si dà un percorso completo per CDLL o cdll.LoadLibrary (), si può ancora bisogno di impostare LD_LIBRARY_PATH prima di richiamare Python. Se la libreria condivisa si carica esplicitamente fa riferimento a un'altra libreria condivisa e non "rpath" è impostato nel .so per quella libreria, allora non essere trovato, anche se è già stato caricato. Un rpath in una biblioteca specifica un percorso di ricerca da utilizzare per la ricerca di altre librerie richieste da quella biblioteca

Per esempio, ho un caso di un insieme di librerie di terze parti interdipendenti non prodotti da me. b.so riferimenti a.so. Anche se carico a.so in anticipo:

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

ottengo un errore sul secondo carico, in quanto si riferisce a b.so semplicemente 'a.so', senza un rpath, e così b.so non sa che è la corretta a.so. Quindi devo impostare LD_LIBRARY_PATH in anticipo per includere '/ abs / path / to'.

Per evitare di dover impostare LD_LIBRARY_PATH, si modifica la voce rpath nei file .so. Su Linux, ci sono due utility che ho trovato che fanno questo: chrpath e patchelf . chrpath è disponibile nei repository di Ubuntu. Non può cambiare rpath su .so di che non hanno mai avuto uno. patchelf è più flessibile.

CDLL può essere passato un nome percorso completo, così per esempio sto utilizzando il seguente in uno dei miei script in cui il .so si trova nella stessa directory dello script python.

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

Nel tuo caso il seguente dovrebbe essere sufficiente.

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

Compilare il binario con un rpath relativo alla directory di lavoro corrente come:

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

Poi, si è in grado di cambiare la directory di lavoro in Python a runtime con:

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

In questo modo, il caricatore trova anche altre librerie dinamiche come otherbinary.so

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top