2012-02-04 8 views
5

Sto cercando di ottenere un codice accademico open source funzionante (il progetto home è here). È una grande base di codice C++ con un wrapper python (molto) sottile che utilizza CDLL per caricare il C++ e chiamare alcune funzioni C disponibili per consentire lo scripting Python primitivo del codice.python che carica c lib con CDLL, non vede le librerie nel percorso python

Tuttavia, il codice iniziale di importazione si blocca perché non riesce a trovare i file .so seduti accanto ad essa in site-packages:

nel file installato:

from ctypes import * 

try: 
    self.lib = CDLL("_lammps.so") 
except: 
    try: 
    self.lib = CDLL("_lammps_serial.so") 
    except: 
    raise OSError,"Could not load LAMMPS dynamic library" 

e in uno script o l'interprete:

from lammps import lammps 
l = lammps() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "lammps.py", line 42, in __init__ 
    raise OSError,"Could not load LAMMPS dynamic library" 
OSError: Could not load LAMMPS dynamic library 

altre risposte might seem to have this covered, ma questo funziona solo se CDLL() è chiamato all'interno dello script in realtà invocato (o la directory di lavoro del prompt che ha eseguito l'interprete), cioè se il 'percorso relativo' è nello spazio utente, piuttosto che in python-library-space.

Come installiamo in modo affidabile per importare una libreria C/C++ che abbiamo creato da soli? A corto di inquinare le posizioni delle librerie di sistema come /usr/lib, che non è molto pitone, non riesco a vedere una soluzione facile.

(EDIT: corretto nomi delle funzioni, refactoring chiaro inutile dispiace!!)

+0

ulteriore: la libreria in questione aveva un simbolo mancante, quindi questo codice avrebbe potuto mascherare un errore diverso; non si dovrebbe presumere di sapere qual è l'eccezione di sistema e lanciare la tua! In realtà, la domanda è ancora valida dopo ulteriori indagini; il sistema * stava * lanciando l'errore corretto la prima volta (ho provato questo copiando il file .so in '/ usr/lib' ed eseguendo' CDLL() 'dal prompt interattivo.) – tehwalrus

risposta

1

Run sotto strace -eopen, si vedrà qualcosa di simile:

open("tls/x86_64/_lammps.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 
open("tls/_lammps.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 
open("x86_64/_lammps.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 
open("_lammps.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 6 
open("/lib/_lammps.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 
open("/usr/lib/_lammps.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 

Quali mostra tutti i luoghi in cui pitone ctypes cerca la tua libreria. Finora non sono stato in grado di trovare un tweak di variabile di ambiente di runtime per farlo aggiungere posizioni di ricerca sul mio sistema, forse devi usare percorsi assoluti.

+0

grazie, cercherò questo quando Ho un momento. Sono su Mac OS X, quindi dovrò trasferire il tuo strace suggerimento su dtrace (che si spera non dovrebbe essere troppo cattivo). – tehwalrus

1

È possibile utilizzare la variabile __file__ nel pacchetto che sta eseguendo l'importazione. È sufficiente utilizzare le varie funzioni di os.path per estrarre il percorso completo e completo della directory da __file__ e quindi aggiungerlo al nome file della libreria. Qualcosa di simile:

temp = os.path.abspath(__file__) 
temp = os.path.realpath(temp) 
temp = os.path.dirname(temp) 
temp = os.path.join(temp, "_lammps.so") 
lib = CDLL(path) 

Si potrebbe anche voler provare diverse varianti del vostro nome del file di base (ad esempio, con .dll o .dylib invece di .so, e con e senza un prefisso lib, e forse anche con numeri di versione in allegato) se vuoi essere indipendente dalla piattaforma e il tuo sistema di compilazione potrebbe produrre tali cose. Potresti quindi provare diverse versioni o semplicemente utilizzare glob.glob per aiutarti a trovarne uno accettabile.

Devo dire che penso sia strano che nessuna funzione di questo tipo esista nella libreria standard. Il non è abbastanza flessibile (o approfondito) abbastanza per questo tipo di utilizzo (che credo sarebbe diffuso). Anche solo una funzione che ha cercato tramite il file PYTHONPATH per il file sarebbe stata abbastanza utile (anche se non è difficile da scrivere).

Quindi, ancora una volta, sembra che se si aggiunge la directory giusta a LD_LIBRARY_PATH, si should be able to load it.

2

Im su Linux, tutto quello che ho fatto per risolvere questo problema è stato messo nel percorso assoluto del modulo os, e funziona

from ctypes import * 
import os 

xss = cdll.LoadLibrary(os.path.abspath("libxss.so.1")) 
print xss.xss_test_1() 

Questo è python 2.7 pure.

Problemi correlati