如何在运行时更新此环境变量,以便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")
答案 0 :(得分:41)
当Python等程序运行时,动态加载程序(ld.so.1或类似的东西)已经读取了LD_LIBRARY_PATH,此后不会发现任何更改。因此,除非Python软件本身评估LD_LIBRARY_PATH并使用它来为dlopen()
或等效函数构建库的可能路径名,否则在脚本中设置变量将不起作用。
鉴于你说它不起作用,假设Python不构建并尝试所有可能的库名称似乎是合理的;它可能仅依赖于LD_LIBRARY_PATH。
答案 1 :(得分:26)
即使您提供CDLL或cdll.LoadLibrary()的完全限定路径,您仍可能需要在调用Python之前设置LD_LIBRARY_PATH。如果您明确加载的共享库引用另一个共享库,并且该库中的.so中没有设置“rpath”,那么即使它已经加载也不会找到它。库中的rpath指定用于搜索该库所需的其他库的搜索路径
例如,我有一组不依赖于我的第三方库的情况。 b。参考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更灵活。
答案 2 :(得分:15)
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")
答案 3 :(得分:3)
使用相对于当前工作目录的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
答案 4 :(得分:1)
将LD_LIBRARY_PATH设置为放置库的路径在这里不起作用,并且ctypes不会注意到任何更改。因此,您需要在源代码中进行此操作,并在脚本之前将ldconfig纳入考虑范围。此外,在脚本中设置os环境或任何PATH变量都将无效。
我面临类似的问题,花了整整一天的时间来解决这个问题。
#mkdir -p /etc/ld.so.conf.d/
#echo "/home/starlon/Projects/pyCFA635/lib" > /etc/ld.so.conf.d/mycustomPath.conf
#ldconfig
然后验证是否设置了路径 通过
# ldconfig -v | less
完成此操作后,尝试运行脚本。这为我工作,也应该为之工作。
您可以在下面看到的URL帮助我解决了这个问题:
https://www.cyberciti.biz/faq/linux-setting-changing-library-path/
注意:我意识到问题很老,但是想为这个问题做点贡献,因为仅被接受的答案并不能真正解决问题。