用CDLL加載c庫的python,在python路徑中看不到庫

[英]python loading c lib with CDLL, doesn't see libraries in the python path


I'm trying to get some open source academic code working (the project home is here). It is a big C++ codebase with a (very) thin python wrapper which uses CDLL to load the C++ and call some C functions that are available to allow primitive python scripting of the code.

我正在嘗試讓一些開放源碼的學術代碼工作(project home在這里)。它是一個大型的c++代碼庫,帶有一個(非常)瘦的python包裝器,它使用CDLL加載c++並調用一些C函數,這些函數可用來支持代碼的原始python腳本。

However, the initial import code crashes because it can't find the .so files sitting next to it in site-packages:

但是,初始的導入代碼會崩潰,因為它找不到位於它旁邊的.so文件在站點包中:

in the installed file:

在安裝文件中:

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"

and in a script or the interpreter:

在劇本或翻譯中:

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

Other answers might seem to have this covered, but this only works if CDLL() is called within the script actually invoked (or the working directory of the prompt that ran the interpreter) - i.e. if the 'relative path' is in user-space, rather than python-library-space.

其他答案似乎也包含了這一點,但只有當在實際調用的腳本(或運行解釋器的提示符的工作目錄)中調用CDLL()時,才會有效——也就是說,如果“相對路徑”在用戶空間中,而不是在python-library-space中。

How do we reliably install for import a C/C++ library that we built ourselves? Short of polluting the system library locations like /usr/lib, which isn't very pythonic, I can't see an easy solution.

如何可靠地安裝導入我們自己構建的C/ c++庫?除了污染像/usr/lib這樣的系統庫位置(這不是很python化)之外,我看不到一個簡單的解決方案。

(EDIT: corrected function names, unclear refactoring unhelpful! sorry!)

(編輯:修改函數名,重構不清晰,沒有幫助!對不起!)

3 个解决方案

#1


2  

Im on linux, all I did to fix this issue was put in the absolute path from the os module, and it works

在linux上的Im,我所做的修復這個問題的所有工作都放在了操作系統模塊的絕對路徑中,並且它是有效的

from ctypes import *
import os

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

This is python 2.7 as well.

這也是python 2。7。

#2


1  

Run under strace -eopen, you will see something like this:

在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)

Which shows you all the locations where python ctypes looks for your library. So far I was unable to find a runtime environment variable tweak to make it to add search locations on my system, perhaps you have to use absolute paths.

它向您展示了python ctype查找庫的所有位置。到目前為止,我還無法找到一個運行時環境變量調整,使它在我的系統中添加搜索位置,也許您必須使用絕對路徑。

#3


1  

You could use the __file__ variable in the package that is doing the importing. Just use the various functions of os.path to extract the full, absolute directory path from __file__, and then join it to your library filename. Something like:

您可以在執行導入的包中使用__file__變量。使用os的各種函數。從__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)

You might also want to try various variations of your core filename (i.e., with .dll or .dylib instead of .so, and with and without a lib prefix, and perhaps even with version numbers appended) if you want to be platform-independent, and your build system could possibly produce such stuff. You could then either try several versions, or just use glob.glob to help you find an acceptable one.

您可能還想嘗試各種不同的核心文件名(即:如果您希望獨立於平台,那么您的構建系統可能會生成這樣的東西。然后您可以嘗試幾個版本,或者只使用glob。幫助你找到一個可以接受的。

I've got to say I think it's odd that no such function exists in the standard library. The ctypes.util.find_library isn't quite flexible (or thorough) enough for this kind of use (which I would think was widespread). Even just a function that searched through PYTHONPATH for the file would have been quite useful (though not hard to write).

我不得不說,我認為標准庫中不存在這樣的函數是很奇怪的。ctypes.util。find_library不夠靈活(或者不夠全面),不適合這種用途(我認為這種用途很普遍)。即使只是通過python路徑搜索文件的函數也會非常有用(盡管編寫起來並不困難)。

Then again, it seems that if you just add the right directory to LD_LIBRARY_PATH, you should be able to load it.

同樣,如果您只是將正確的目錄添加到LD_LIBRARY_PATH,那么您應該能夠加載它。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2012/02/04/c6588fce7e6da9f5ab1b8da1fa53cd30.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com