ctypes.cdll 以及如何重新映射@executable_path

问题描述 投票:0回答:0

尝试用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 解释器,以便可执行文件路径具有所需的值? (可能这会破坏应用程序的签名?)

python dyld dynamic-dll-import dyld-insert-libraries
© www.soinside.com 2019 - 2024. All rights reserved.