在运行时更改ctypes的LD_LIBRARY_PATH

如何在运行时更新这个环境variables,以便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等程序正在运行时,dynamic加载器(ld.so.1或类似的东西)已经读取LD_LIBRARY_PATH,并且之后不会注意到任何改变。 因此,除非Python软件本身评估LD_LIBRARY_PATH并使用它来构builddlopen()的函数库的可能path名或者使用等效函数,否则在脚本中设置variables将不起作用。

鉴于你说这是行不通的,假设Python不会构build并尝试所有可能的库名称似乎是合理的。 它可能单独依赖于LD_LIBRARY_PATH。

即使您给CDLL或cdll.LoadLibrary()提供了一个完全合格的path,在调用Python之前,您仍然可能需要设置LD_LIBRARY_PATH。 如果您明确加载的共享库引用了另一个共享库,并且在该库的.so中没有设置“rpath”,那么即使它已经被加载,它也不会被find。 库中的rpath指定要用于search该库所需的其他库的searchpath

例如,我有一个由我制作的一组相互依存的第三方库。 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 / path / to'。

为避免必须设置LD_LIBRARY_PATH,可以修改.so文件中的rpath条目。 在Linux上,我发现有两个实用程序:chrpath和patchelf 。 chrpath可从Ubuntu存储库中获得。 它不能改变.so的rpath从来没有。 patchelf更加灵活。

CDLL可以传递一个完全合格的path名,所以例如我在脚本之一中使用以下内容.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') 

像这样,加载器还可以find像otherbinary.so这样的其他dynamic库