OSX 的 Cython 链接错误

Posted

技术标签:

【中文标题】OSX 的 Cython 链接错误【英文标题】:Cython Link Errors for OSX 【发布时间】:2019-08-26 22:32:13 【问题描述】:

我有一个与SO post 非常相似的问题;但是,在那里实施建议的修复后 - 我仍然收到以下错误。

我正在尝试编译由 Cython 生成的 C 文件。

cython ConnectFour.pyx --embed

我尝试像这样编译我的 c 文件:

gcc -I /usr/local/Cellar/python3/3.7.0/Frameworks/Python.framework/Versions/3.7/Headers -o ConnectFour ConnectFour.c

但是我收到以下错误:

Undefined symbols for architecture x86_64:
  "_PyBaseObject_Type", referenced from:
      ___Pyx_InBases in ConnectFour-3c26d7.o
  "_PyBytes_FromStringAndSize", referenced from:
      ___pyx_pymod_exec_ConnectFour in ConnectFour-3c26d7.o
      ___Pyx_InitStrings in ConnectFour-3c26d7.o
  "_PyCFunction_NewEx", referenced from:
      ___pyx_pymod_exec_ConnectFour in ConnectFour-3c26d7.o
  "_PyCFunction_Type", referenced from:
      ___Pyx_PyObject_CallOneArg in ConnectFour-3c26d7.o
      ___Pyx_PyObject_CallNoArg in ConnectFour-3c26d7.o
      ___Pyx_PyObject_Call2Args in ConnectFour-3c26d7.o
      ___Pyx_PyCFunction_FastCall in ConnectFour-3c26d7.o
      ___pyx_pf_11ConnectFour_36eval_heuristic_score in ConnectFour-3c26d7.o
      ___pyx_pf_11ConnectFour_38list_valid_col_idxs in ConnectFour-3c26d7.o
      ___pyx_pf_11ConnectFour_40deep_copy_board in ConnectFour-3c26d7.o
      ...
  "_PyCode_New", referenced from:
      ___Pyx_InitCachedConstants in ConnectFour-3c26d7.o
      ___Pyx_CreateCodeObjectForTraceback in ConnectFour-3c26d7.o
  "_PyDict_Copy", referenced from:
      ___pyx_pw_11ConnectFour_7profile_1wrapper in ConnectFour-3c26d7.o
      ___pyx_pw_11ConnectFour_5timer_1wrapper in ConnectFour-3c26d7.o
  "_PyDict_GetItemString", referenced from:
      ___pyx_pymod_exec_ConnectFour in ConnectFour-3c26d7.o
  "_PyDict_GetItemWithError", referenced from:
      ___Pyx_PyDict_GetItem in ConnectFour-3c26d7.o
  "_PyDict_New", referenced from:
      ___pyx_pymod_exec_ConnectFour in ConnectFour-3c26d7.o
      ___Pyx_Import in ConnectFour-3c26d7.o
      ___Pyx_CyFunction_get_dict in ConnectFour-3c26d7.o
      ___Pyx_CyFunction_get_annotations in ConnectFour-3c26d7.o
      ___pyx_pf_11ConnectFour_28count_players in ConnectFour-3c26d7.o
      ___pyx_pf_11ConnectFour_52num_in_a_row in ConnectFour-3c26d7.o

我基于this 和this 出现所以我错过了一些图书馆链接?所以我尝试了以下方法。

gcc -I /usr/local/Cellar/python3/3.7.0/Frameworks/Python.framework/Versions/3.7/Headers -o ConnectFour ConnectFour.c -l/usr/local/Cellar/python3/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/libpython3.7.dylib

现在我得到一个 lib not found 错误。

ld: 找不到库 -l/usr/local/Cellar/python3/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/libpython3.7.dylib

阅读所有这些 SO 帖子(第一次与 C 打交道),我完全无法理解,因此将不胜感激。

我需要具备什么才能编译并运行我的 C 文件而不会出错?

我知道我的标头位于/usr/local/Cellar/python3/3.7.0/Frameworks/Python.framework/Versions/3.7/Headers,而库位于/usr/local/Cellar/python3/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/libpython3.7.dylib

我在 OSX 上,我使用 Homebrew 安装了 Python。

【问题讨论】:

对 MacOS 了解不多,但它没有 python-config-utility 可以按此处所述使用:***.com/a/45424720/5769463 是的,我读过那篇文章,但似乎不清楚我实际需要做什么 - 几乎不明白那里的答案哈哈 所以也许你应该从一个简单的模块开始,它可以按照cython.readthedocs.io/en/latest/src/userguide/… 的描述构建并比较使用的命令,例如 cythonize 啊,是的,我确实做到了。我设法从 python 运行我的脚本,但我正试图更上一层楼,即只运行一个来自 C 的可执行文件,但弄清楚它是一场噩梦...... 我明白了,那我恐怕帮不上什么忙了。 【参考方案1】:

所以我最终根据@ead 的建议更仔细地阅读了this SO post,结果证明这对我很有帮助。为遇到类似问题的人编写以下内容。

运行cython ConnectFour.pyx --embed 后,我的目标是将.c 文件编译为可执行文件。这意味着 (1) 需要构建 .o 目标文件和 (2) 将 .o 目标文件转换为可运行的可执行文件,如下所示:./MyExecutable

步骤 1. 构建 .o 目标文件

我们需要运行以下命令,但我遇到的问题是找出如何获取我的标志。

gcc -c hello.c -o hello.o <our cflags>

由于我是通过 Homebrew 安装 Python,Python 及其头文件对我来说位于以下目录中。

/usr/local/Cellar/python3/3.7.0/Frameworks/Python.framework/Versions/3.7/bin/

为了为我生成 cflags - 我必须运行以下命令。注意 --cflags 标志。该命令为我的 Python 3 安装运行配置实用程序,该实用程序安装在奇怪的目录中(因为我通过 Homebrew 安装了 Python)。

/usr/local/Cellar/python3/3.7.0/Frameworks/Python.framework/Versions/3.7/bin/python3.7-config
--cflags

下面是它为我生成的标志的 sn-p。

-I/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/include/python3.7m -I/usr/local.......etc etc.

使用标志我运行以下命令来生成我的目标文件。

gcc -c ConnectFour.c -o ConnectFour.o -I/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/include/python3.7m -I/...etc etc.

步骤 2. 将目标文件转换为可执行文件

为了生成可执行文件,我们需要运行以下命令。

gcc main.o hello.o -o prog <our ldflags>

要生成 ldflags,这次我需要运行以下命令。我们再次使用配置实用程序,但这次使用 --ldflags。

/usr/local/Cellar/python3/3.7.0/Frameworks/Python.framework/Versions/3.7/bin/python3.7-config --ldflags

这为我生成了以下标志。

-L/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/config-3.7m-darwin -lpython3.7m ...etc. etc.

使用这些标志,我运行以下命令来生成我的可执行文件。

gcc ConnectFour.o -o ConnectFour -L/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/config-3.7m-darwin -lpython3.7m ...etc. etc.

完成!弹出一个可执行文件,我像运行任何其他 C 可执行文件一样运行它。

特别感谢@ead 为我指明了正确的方向。

【讨论】:

【参考方案2】:

尝试运行

gcc -I /usr/local/Cellar/python3/3.7.0/Frameworks/Python.framework/Versions/3.7/Headers -o ConnectFour ConnectFour.c -L/usr/local/Cellar/python3/3.7.0/Frameworks/Python.framework/Versions/3.7 -lpython3.7

-L 标志将该目录添加到搜索路径,然后使用 -l 链接(因为 -l 似乎不接受绝对路径),在 Linux 上,使用 -l 时至少省略 lib 前缀和扩展名,我从未使用过 MacOSX,所以如果不起作用,请尝试不同的组合。

【讨论】:

以上是关于OSX 的 Cython 链接错误的主要内容,如果未能解决你的问题,请参考以下文章

OSX链接错误的Fabric Answers

OSX 命令行应用程序链接器错误

OSX上的clang:-finstrument-functions链接错误

在 OSX El Capitan 中使用 Homebrew 的 Boost::Log 链接错误

如何在 Mac OSX 上将 DCMTK 与 Qt 链接

Mac 上的 G++ 链接时优化 - 编译器/链接器错误?