2012-02-04 153 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为好。