在运行时更改为LD_LIBRARY_PATH ctypes的
题
如何在运行时更新此环境变量,这样的ctypes可以加载一个库哪里?我已经试过以下既不似乎工作。
from ctypes import *
os.environ['LD_LIBRARY_PATH'] = "/home/starlon/Projects/pyCFA635/lib"
os.putenv('LD_LIBRARY_PATH', "/home/starlon/Projects/pyCFA635/lib")
lib = CDLL("libevaluator.so")
解决方案
通过程序例如Python正在运行时,动态加载器(程序ld.so.1或类似的东西)已经阅读LD_LIBRARY_PATH并且此后不会注意到任何变化。所以,除非Python的软件本身计算LD_LIBRARY_PATH并用它来建立dlopen()
或使用同等功能库的可能路径名,设定在脚本中的变量将没有任何效果。
,它似乎是合理的假设,Python没有建立,并尝试所有可能的库名;它可能依赖于单独LD_LIBRARY_PATH。
其他提示
即使你给CDLL或cdll.LoadLibrary()一个完全合格的路径,你可能还需要调用的Python之前设置LD_LIBRARY_PATH。如果你明确地加载共享库指的是另一个共享库,并没有“rpath中”的。所以对于磁带库设置,那么它将不会被发现,即使已经装好了。在库中的rpath中指定要用于搜索由该库
所需的其它文库的搜索路径例如,我有一组不通过我产生相互依赖第三方库的的情况。 b.so引用a.so.即使我加载a.so提前:
ctypes.cdll.LoadLibrary('/abs/path/to/a.so')
ctypes.cdll.LoadLibrary('/abs/path/to/b.so')
我得到的第二负载一个错误,因为b.so指的是简单的“a.so”,没有rpath的,所以b.so不知道这是正确的a.so.所以,我必须提前设置到LD_LIBRARY_PATH包括“/ ABS /路径/到”。
要避免不必设置LD_LIBRARY_PATH,修改在.so文件将rpath条目。在Linux中,有两个工具,我发现这样做:chrpath和 patchelf 。 chrpath可以从Ubuntu软件仓库。它不能上的.so的是从未有过改变rpath的。 patchelf是更灵活的。
CDLL可以传递一个完全合格的路径名,因此,例如我用我的剧本之一,其中的.so是在同一目录中python脚本如下。
import os
path = os.path.dirname(os.path.realpath(__file__))
dll = CDLL("%s/iface.so"%path)
在您的情况下,下面就足够了。
from ctypes import *
lib = CDLL("/home/starlon/Projects/pyCFA635/lib/libevaluator.so")
相对于像当前工作目录一个rpath的编译二进制文件:
gcc -shared -o yourbinary.so yoursource.c otherbinary.so \
-Wl,-rpath='.',-rpath='./another/relative/rpath' -fpic
然后,您就可以在与运行时改变工作目录中的Python:
import os
os.chdir('/path/to/your/binaries')
像这样,加载器还发现其他动态库等的 otherbinary.so