python使用CDLL加载c-lib,不会';在python路径中看不到库

python使用CDLL加载c-lib,不会';在python路径中看不到库,python,ctypes,lammps,Python,Ctypes,Lammps,我正试图让一些开源学术代码发挥作用(项目主页是)。它是一个很大的C++代码库,它使用非常薄的Python包装器,使用 CDLL< /Cord>加载C++并调用一些允许原始Python脚本编写代码的C函数。 但是,初始导入代码崩溃,因为它在站点包中找不到它旁边的.so文件: 在安装的文件中: 从ctypes导入* 尝试: self.lib=CDLL(“\u lammps.so”) 除: 尝试: self.lib=CDLL(“\u lammps\u serial.so”) 除: 引发操作错误,“无法

我正试图让一些开源学术代码发挥作用(项目主页是)。它是一个很大的C++代码库,它使用非常薄的Python包装器,使用<代码> CDLL< /Cord>加载C++并调用一些允许原始Python脚本编写代码的C函数。 但是,初始导入代码崩溃,因为它在站点包中找不到它旁边的.so文件:

在安装的文件中:

从ctypes导入*
尝试:
self.lib=CDLL(“\u lammps.so”)
除:
尝试:
self.lib=CDLL(“\u lammps\u serial.so”)
除:
引发操作错误,“无法加载LAMMPS动态库”
在脚本或解释器中:

从lammps导入lammps
l=lammps()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“lammps.py”,第42行,在_init中__
引发操作错误,“无法加载LAMMPS动态库”
OSError:无法加载LAMMPS动态库
其他答案,但这仅在实际调用的脚本(或运行解释器的提示符的工作目录)中调用
CDLL()
时有效,即“相对路径”位于用户空间,而不是python库空间

我们如何可靠地安装并导入我们自己构建的C/C++库?除了污染系统库的位置,比如
/usr/lib
,它不是很pythonic,我看不到一个简单的解决方案


(编辑:更正了函数名,重构不清晰没有帮助!抱歉!)

在strace-eopen下运行,您将看到如下内容:

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)
这将显示python ctypes查找库的所有位置。
到目前为止,我无法找到运行时环境变量tweak,以便在我的系统上添加搜索位置,可能您必须使用绝对路径。

您可以使用正在进行导入的包中的
\uuuu文件
变量。只需使用
os.path
的各种功能从
\uuuuu文件\uuuuu
中提取完整的绝对目录路径,然后将其加入到库文件名中。比如:

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_库
不够灵活(或彻底),不适合这种用法(我认为这种用法很普遍)。即使只是一个在PYTHONPATH中搜索文件的函数也会非常有用(尽管编写起来并不困难)


再一次,如果您只是将正确的目录添加到
LD\u LIBRARY\u PATH
,那么您就可以在linux上使用Im。

I解决这个问题,我所做的一切就是将它放在操作系统模块的绝对路径中,并且可以正常工作

from ctypes import *
import os

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

这也是python 2.7。

必须指定绝对路径。请尝试以下操作:

import os
from ctypes import *

try:
  slib = os.getcwd() + '/' +'_lammps.so'
  hlibc = CDLL(slib)
  hilbc.FunctionName()
except:
  try:
    slib = os.getcwd() + '/' +'_lammps_serial.so'
    hlibc = CDLL(slib)
  except:
    raise OSError,"Could not load LAMMPS dynamic library"

在通过ctypes导入相关LIB之前,将相关文件夹放入PATH变量中

例如,如果libs(dll,…)与.py文件位于同一文件夹中:

import os
os.environ["PATH"] += os.pathsep + os.path.dirname(os.path.abspath(__file__))

这不会将任何内容写入系统路径。它将只为这个实例设置它。

进一步:所讨论的库缺少一个符号,因此该代码可能掩盖了另一个错误;人们不应该假设您知道系统异常是什么,然后抛出自己的异常!事实上,经过进一步调查,这个问题仍然有效;系统第一次抛出了正确的错误(我通过将.so复制到
/usr/lib
并从交互提示运行
CDLL()
来测试此错误)。谢谢,我会在有时间时对此进行研究。我使用的是MacOSX,所以我必须将您的strace建议移植到dtrace(希望不会太糟糕)。