2009-05-13 25 views
29

Jak zaktualizować tę zmienną środowiskową w czasie wykonywania, aby ctypes mógł załadować bibliotekę gdziekolwiek? Próbowałem następujące i nic nie działa.Zmienianie LD_LIBRARY_PATH w czasie wykonywania dla ctypów

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") 

Odpowiedz

35

W czasie programu, takich jak Python jest uruchomiony, dynamiczny ładowarka (ld.so.1 lub coś podobnego) już czytać LD_LIBRARY_PATH i nie zauważą żadnych zmian w kolejnych latach. Tak więc, chyba że samo oprogramowanie Python ocenia LD_LIBRARY_PATH i używa go do budowania możliwej nazwy ścieżki biblioteki dla dlopen() lub równoważnej funkcji do użycia, ustawienie zmiennej w skrypcie nie przyniesie żadnego efektu.

Zakładając, że nie działa, wydaje się prawdopodobne, że Python nie buduje i nie wypróbowuje wszystkich możliwych nazw bibliotek; prawdopodobnie opiera się tylko na LD_LIBRARY_PATH.

+5

to diagnozuje problem, ale go nie rozwiązuje. – dbliss

13

CDLL można przekazać pełną nazwę ścieżki, więc na przykład używam następujących w jednym z moich skryptów, gdzie .so znajduje się w tym samym katalogu, co skrypt Pythona.

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

W twoim przypadku wystarczą poniższe.

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

Nawet jeśli dają pełną ścieżkę do CDLL lub cdll.LoadLibrary(), może trzeba jeszcze ustawić LD_LIBRARY_PATH przed wywołaniem Python. Jeśli udostępniona biblioteka jest ładowana jawnie, odwołuje się do innej biblioteki współużytkowanej i nie ustawiono "rpath" w .so dla tej biblioteki, to nie zostanie znaleziona, nawet jeśli została już załadowana. Ścieżka rpath w bibliotece określa ścieżkę wyszukiwania, która ma być używana do wyszukiwania innych bibliotek potrzebnych dla tej biblioteki. Na przykład, mam przypadek zestawu niezależnych bibliotek innych producentów, które nie zostały wyprodukowane przeze mnie. b.so odnosi się do a.so. Nawet jeśli załadować a.so z góry:

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

pojawia się błąd na drugim obciążeniu, ponieważ b.so oznacza po prostu „a.so”, bez rPath, a więc b.so robi” t wiem, że to jest poprawne a.so. Dlatego muszę wcześniej ustawić LD_LIBRARY_PATH, aby uwzględnić "/ abs/path/to".

Aby uniknąć konieczności ustawiania LD_LIBRARY_PATH, należy zmodyfikować wpis rpath w plikach .so. W Linuksie są dwa narzędzia, które mogę to zrobić: chrpath i patchelf. chrpath jest dostępna z repozytoriów Ubuntu. Nie można zmienić ścieżki na .so, która nigdy nie miała. patchelf jest bardziej elastyczny.

1

kompilacji plik binarny z rpath względem bieżącego katalogu roboczego jak:

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

Wtedy jesteś w stanie zmienić katalog roboczy w python przy starcie z:

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

lubię tego program ładujący znajduje także inne biblioteki dynamiczne, takie jak , innebinary.so

+0

Działa to tylko wtedy, gdy katalog roboczy procesu ładującego bibliotekę jest katalogiem biblioteki. W przeciwnym razie względna ścieżka środowiska wykonawczego nie może znaleźć zależności, której katalog jest względny względem biblioteki. – danny

Powiązane problemy