在运行时更改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库