【发布时间】:2020-05-24 05:42:04
【问题描述】:
背景
我已经阅读了无数的 GitHub 项目线程以及我在 StackOverflow 上可以找到的有关此问题的所有内容,尽管到目前为止还没有运气。我有一个运行库存 CommandLineTools 和/或 Xcode 的 Mac 10.14 机器。我正在尝试“移植”一个 Python 包装器库,我在 Python3 中使用 CTypes 围绕一个较旧的 C 和 C++ 库编写。它已经在 Ubuntu Linux 上运行良好。但是,自从迁移到 Mac 平台以来,我遇到的问题没有尽头。现在似乎没有一个简单的答案来修复我正在尝试在损坏的 Mac OS 平台上做的事情——至少对于像我这样的外行 Linux 人来说是这样。
在描述我如何编译我正在尝试使用 CTypes 加载的 dylib 之前,我有一个问题:我现在是否需要以某种方式签署我的 dylib 才能在 Mac 上使用它10.14? 否则,我想我的问题可以归结为 $%^@(我现在的意思是被截断了)如何在 Mac 上使用 Python C 扩展处理共享/动态库界面?
我的偏好是甚至不接触 Xcode,而只使用系统自带的开箱即用的 Mac 工具。我的解决方案必须在命令行上运行,而不需要遵循 Xcode 将以 GUI 形式提供给您的一些自动配置魔法。真的,这对于 Linux 下的一切来说都是相当轻松的。
编译和链接
实际情况比我描述的要复杂。我将仅勾勒出在我看来是解决方案的相关部分,然后让所有已经完成这项工作的专家告诉我两者之间明显的失误。
我首先使用以下代码将较旧的 C/C++ 源代码库编译为静态存档 Mac 上的 gcc(读取 clang)选项(其中一些被忽略):
-O0 -march=native -force_cpusubtype_ALL -fPIC -I../include -fPIC -m64 \
-fvisibility=default -Wno-error -lc++ -lc++abi
然后我用组合编译和链接
-Wl,-all_load $(LIBGOMPSTATIC).a $(LIBGMPSTATIC) -Wl,-noall_load \
-ldl -lpthread -lc++ -lc++abi
和
-dynamiclib -install_name $(MODULENAME) \
-current_version 1.0.0 -compatibility_version 1.0
生成 dylib 输出。
为了比较,在 Linux 上,这些标志的类似物大约是
-Wl,-export-dynamic -Wl,--no-undefined -shared -fPIC \
-fvisibility=default -Wl,-Bsymbolic
-Wl,-Bstatic -Wl,--whole-archive $(LIBGOMPSTATIC).a $(LIBGMPSTATIC) -Wl,--no-whole-archive \
-Wl,-Bdynamic -Wl,--no-as-needed -ldl -lpthread
和
-Wl,-soname,$(MODULENAME)
dylib 输出
上面的过程给了我一个 dylib 文件,我可以用nm 扫描它以查看我尝试用 CTypes 导入的符号。这是一个好的开始。当我尝试运行测试 python 脚本来测试我的 CTypes 包装库时,我立即得到一个 SEGFAULT。由于 gdb 这些天在 Mac 上显然没用(对不起),我使用股票 llvm 加载带有额外调试符号的 brew 安装的 python3:
lldb /usr/local/Cellar/python-dbg\@3.7/3.7.6_13/bin/python3
(lldb) run myscript.py
Process 75435 launched: '/usr/local/Cellar/python-dbg@3.7/3.7.6_13/bin/python3' (x86_64)
Process 75435 stopped
* thread #2, stop reason = exec
frame #0: 0x0000000100005000 dyld`_dyld_start
dyld`_dyld_start:
-> 0x100005000 <+0>: popq %rdi
0x100005001 <+1>: pushq $0x0
0x100005003 <+3>: movq %rsp, %rbp
0x100005006 <+6>: andq $-0x10, %rsp
Target 0: (Python) stopped.
(lldb) bt
* thread #2, stop reason = exec
* frame #0: 0x0000000100005000 dyld`_dyld_start
(lldb) c
... redacted path information ...
File "/usr/local/Cellar/python-dbg@3.7/3.7.6_13/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ctypes/__init__.py", line 442, in LoadLibrary
return self._dlltype(name)
File "/usr/local/Cellar/python-dbg@3.7/3.7.6_13/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ctypes/__init__.py", line 364, in __init__
self._handle = _dlopen(self._name, mode)
OSError: dlopen(GTFoldPython.dylib, 6): image not found
Process 75435 exited with status = 1 (0x00000001)
我确实将每个环境变量 PYTHONAPPSDIR=/usr/local/Cellar/python-dbg@3.7/3.7.6_13、PYTHONPATH、LD_LIBRARY_PATH、DYLD_LIBRARY_PATH 设置为正确的路径。
所以问题是我接下来要尝试什么才能使其正常工作?提前很多很多小时的感谢!
【问题讨论】:
-
函数
ctypes.PyDLL("mylib.so")在 Linux 上对我有效,但在 Mac 上无效。至少有时可以开始调用ctypes.LoadLibrary("dylib.dylib")。如果有帮助,我可以在 CTypes 中发布更多我的 Python 包装器代码。 -
什么是
GTFoldPython.dylib?好像找不到那个dylib。 -
dylib
GTFoldPython.dylib是我创建的动态库(在上面的评论中称之为mylib.dylib)。它位于我在帖子中的环境变量的路径中。 -
你知道我是否需要签署 dylib 才能打开它并在 Mojave++ 上使用它吗?我必须经历创建软件签名证书的过程才能使用
gdb(大概lldb在安装时自动配置为这样)。这是我不清楚的一种可能性。另一个是奇怪的路径变量,但这在 Linux 上运行良好。 -
再一次,在我看来,dylib 正在正确编译和链接。我可以用
nm看到我想要的所有符号。只是用 Python3 中的标准 CTypes 构造加载它在 Mac 上太痛苦了!
标签: python-3.x macos ctypes python-c-api dylib