2012-02-04 59 views
5

我試圖讓一些開源學術代碼工作(項目主頁是here)。它是一個很大的C++代碼庫,它有一個非常薄的python包裝器,它使用CDLL來加載C++並調用一些可用的C函數來允許代碼的原始python腳本。python加載與CDLL c lib,沒有看到python路徑中的庫

然而,最初的導入代碼崩潰,因爲它無法找到.so文件坐在旁邊給它的站點包:

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" 

,並在腳本:

在安裝文件

或解釋:

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 

其他答案might seem to have this covered,但這隻適用於如果CDLL()實際上是調用腳本中調用(或工作目錄在運行解釋器的提示符處) - 即,如果'相對路徑'在用戶空間而不是python-library-space中。

我們如何可靠地安裝導入我們自己構建的C/C++庫?對污染系統庫位置如/usr/lib這不是很pythonic,我看不到一個簡單的解決方案。

(編輯:更正函數名,重構不清楚無益的後悔!)下使用strace -eopen

+0

更進一步:有問題的庫有一個符號丟失,所以這段代碼可能掩蓋了一個不同的錯誤;人們不應該假設你知道系統異常是什麼,並拋出你自己的!事實上,這個問題在進一步調查後仍然有效;系統*是第一次拋出正確的錯誤(我通過將.so複製到'/ usr/lib'並在交互式提示符下運行'CDLL()'來測試。) – tehwalrus 2012-02-05 10:35:09

回答

1

運行,你會看到這樣的事情:

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) 

它會顯示所有的位置,其中蟒蛇ctypes尋找你的圖書館。 到目前爲止,我無法找到一個運行時環境變量調整,使其在我的系統上添加搜索位置,也許你必須使用絕對路徑。

+0

謝謝,我會在我有一點時間。我在Mac OS X上,所以我不得不將你的strace建議移植到dtrace上(希望不要太糟糕)。 – tehwalrus 2012-02-07 15:06:53

1

您可以在執行導入的包中使用__file__變量。只需使用os.path的各種功能從__file__中提取完整的絕對目錄路徑,然後將其加入到您的庫文件名。喜歡的東西:

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) 

您也可能想嘗試你的核心文件名的各種變化(即與.dll.dylib代替.so,並且有和沒有一個lib前綴,甚至有版本號追加)如果你想成爲平臺獨立的,你的構建系統可能會產生這樣的東西。然後,您可以嘗試多個版本,或者使用glob.glob來幫助您找到可接受的版本。

我不得不說我認爲奇怪的是標準庫中沒有這樣的函數。 ctypes.util.find_library不足夠靈活(或徹底),這種用途(我認爲這是普遍的)。即使只是一個通過文件搜索PYTHONPATH的功能將是非常有用的(雖然不難寫)。

然後再次,似乎如果您只是將正確的目錄添加到LD_LIBRARY_PATH,您的should be able to load it

2

林在Linux上,我所做的來解決這個問題置於從os模塊的絕對路徑,和它的作品

from ctypes import * 
import os 

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

這是蟒蛇2.7爲好。