python使用CDLL加载c库,在python路径中看不到库

2024-05-19 03:20:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用一些开源学术代码(项目主页是here)。它是一个很大的C++代码库,它有一个非常瘦的Python包装器,它使用^ {CD1}}加载C++,调用一些C函数,这些函数允许原始的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库空间。

如何可靠地导入我们自己构建的C/C++库?除了像/usr/lib这样的系统库位置污染,这不是什么易事,我看不到一个简单的解决方案。

(编辑:修改了函数名,重构不清晰,没有帮助!对不起!)


Tags: 文件函数代码脚本soliblibrarynot
3条回答

在linux上,我所做的所有修复这个问题的工作都放在操作系统模块的绝对路径中,并且它可以工作

from ctypes import *
import os

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

这也是Python2.7。

在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查找库的所有位置。 到目前为止,我还无法找到运行时环境变量调整,使其能够在我的系统上添加搜索位置,也许您必须使用绝对路径。

您可以在执行导入的包中使用__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

相关问题 更多 >

    热门问题