尝试用cdll加载第三方库:
import ctypes, os
lib_dir = '/path/to/directory/containing'
# this won't work:
#os.environ['DYLD_LIBRARY_PATH'] = lib_dir
lib = ctypes.CDLL(os.path.join(lib_dir, 'theLib.dylib'))
但是库“theLib.dylib”(虚拟名称)有一些依赖项,这些依赖项是相对于
@executable_path
指定的,因此当从Python加载库时,@executable_path
是python3
可执行文件的路径而不是路径原始应用程序本身,因此找不到依赖库:
Traceback (most recent call last):
lib = lib = ctypes.CDLL(os.path.join(lib_dir, 'theLib.dylib'))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/[email protected]/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/python3.11/ctypes/__init__.py", line 376, in __init__
self._handle = _dlopen(self._name, mode)
^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: dlopen(/path/to/directory/containing/theLib.dylib, 0x0006):
Library not loaded: @executable_path/../Frameworks/libqscintilla2_qt5.13.dylib
Referenced from: <E0DE6A39-96C2-35A2-9F4F-1020295BB09B> /path/to/directory/containing/theLib.dylib
Reason: tried:
'/opt/homebrew/Cellar/[email protected]/3.11.3/Frameworks/Python.framework/Versions/3.11/Resources/Python.app/Contents/Frameworks/libqscintilla2_qt5.13.dylib' (no such file),
'/usr/local/lib/libqscintilla2_qt5.13.dylib' (no such file),
'/usr/lib/libqscintilla2_qt5.13.dylib' (no such file, not in dyld cache)
使用
install_name_tool
可以永久修改正在加载的库以将 @executable_path/../Frameworks/libqscintilla2_qt5.13.dylib
重写为其他内容,例如只是 libqscintilla2_qt5.13.dylib
但我不想这样做,因为它破坏了原始应用程序的库。
我可以将应用程序包中的那些 dylib 符号链接到 /usr/local/lib,dyld 也会尝试加载它们,但这会使我的 /usr/local/lib 变得一团糟...
还有其他选择吗?重新映射
@executable_path
到其他路径on the fly(在库加载时)?
如 dyld 错误中所述,将库插入该 dyld 缓存中?
在
@executable_path
中放置一个包装器可执行文件,它只是 exec()
目标 python 解释器,以便可执行文件路径具有所需的值? (可能这会破坏应用程序的签名?)