【问题标题】:How to use Cython to compile Python 3 into C如何使用 Cython 将 Python 3 编译成 C
【发布时间】:2016-04-04 09:36:35
【问题描述】:

我正在尝试将 Python 3 脚本转换为 C,然后将该 C 文件编译为可执行文件。

我有这个简单的 python 脚本:

def greet(name = ""):
  print("Hello {0}".format(name if len(name) > 0 else "World"))

greet("Mango")

我已使用以下方法将此脚本转换为 C:

cython greet.py -o greet.c

然后我使用以下代码编译了 C 文件:

cc greet.c -o greet

输入最后一条命令后出现错误:

致命错误:Python.h:没有此类文件或目录编译终止。

收到错误后,我回过头来意识到我使用的是 Python3,并且忘记了“cython”后面的“3”。
所以重新编译了python脚本:

cython3 greet.py -o greet.c

然后尝试使用以下命令重新编译 C 文件:

cc greet.c -o greet

再次失败并抛出同样的错误,所以我在 SO 和 Google 上搜索并发现了这些问题:

这些问题中的这些答案都不起作用。

我已经确定我已经使用apt-get installpip install 安装了所有正确的依赖项,遗憾的是我认为它似乎仍然不起作用。

【问题讨论】:

  • 安装python-dev
  • 第一个示例问题的公认答案 - 您是否尝试改用sudo apt-get install python3-dev? (注意3)。在 14.04 上,您需要这样做才能获得 py 3 而不是 2 的开发库。
  • @JRichardSnape 是的,我确信我已经在必要时更改了所有 python 版本,但我会再试一次。
  • 另请注意 - 您可能需要执行特定于次要版本的命令,例如install python3.4-dev
  • 您需要告诉 gcc 标头在哪里(例如,在链接时将带有 -I 的路径传递给编译器或将 -l 传递给库。

标签: python c linux cython ubuntu-16.04


【解决方案1】:

检查文档。光做gcc x.c -o x是不够的。

本页解释编译:http://docs.cython.org/src/reference/compilation.html

还有很多,但直接的答案是:

编译您的 .c 文件会因您的操作系统而异。编写扩展模块的 Python 文档应该有一些关于你的系统的细节。这里我们举一个Linux系统上的例子:

$ gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I/usr/include/python2.7 -o yourmod.so yourmod.c

当然,在您的情况下,它会更接近-I/usr/include/python3.4,甚至是$(pkg-config --libs --cflags python3)。而且你不是用-shared 构建的,因为你想要一个可执行文件。

最短的“这必须工作”的命令集是:

cython3 --embed greet.py -o greet.c
gcc $(pkg-config --libs --cflags python3) greet.c -o greet

如果没有pkg-config,你需要安装它。

【讨论】:

  • 我正在使用这个命令:gcc -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing /usr/include/python3.4 -o test.so test.c 但我仍然得到错误。
  • 如果您遇到同样的错误,请检查您实际安装的标头版本。或者你可以通过使用gcc $(pkg-config --libs --cflags python3) greet.c -o greet 编译来避免所有细节。如果您收到有关缺少main 的错误,则需要使用cython3 --embed greet.py
  • 您的说明已经消除了所有其他错误,但仍然有一个 Must specify package names on the command line.,然后是 pyconfig.h no such file or directory
  • 没关系,我们都会犯错。我使用了更新后的说明,现在出现了几十个undefined reference to 错误,这是否意味着我的源代码中有错误?
  • 未定义的名称是什么?你能粘贴错误吗?
【解决方案2】:

正如@viraptor's answer 向您展示的那样,根据我的评论,您的主要问题是您需要告诉您的C 编译器(例如gcc)在哪里可以找到所需的python 头文件(pyconfig.hPython.h)。为此,您需要将-I 选项传递给gcc

另一个答案建议使用pkg-config 将其添加到您的命令行。但是,像您一样,安装了 Ubuntu 14.04、cython3python3-dev,使用这种方法会导致编译的程序退出并出现分段错误。

所以,我建议你回到基础。之后

cython greet.py -o greet.c

运行以下命令。它假定Python.h 和朋友在标准位置(即您已经完成了python3-dev 的标准安装)

gcc -I/usr/include/python3.4m -o greet greet.c -lpython3.4m

如果这不起作用 - 使用 find / -iname Python.h 查找必要文件的位置并相应地更改 -I 路径。

当您想在更复杂的程序(例如链接到其他 C 库的程序)上使用 cython 时,您需要了解需要传递给 gcc 以使其编译的其他选项并正确链接。不过,为了让您继续前进,上述内容应该可以工作(根据您的规范在 Ubuntu 14.04 上测试)

附:我不确定为什么 pkg-config 的建议不起作用 - 但对我来说,它似乎添加了一个额外的路径到 -I 这会破坏事情。

【讨论】:

  • 我有一堆Python.h,一个用于每个Conda env,用于Pycharm,用于vscode等。其中一些是小案例python.h。我可能应该尝试激活的 conda env 中的那个。
【解决方案3】:

Python 2:

python -m pip install --upgrade cython

Python 3:

python3 -m pip install --upgrade cython

【讨论】:

  • 这看起来像您更新 Cython 的方式。然而,问题是如何编译 Cython 生成的 C 文件
  • 如果你实际测试过,使用我的方法,问题完全解决了。
  • 也许你应该解释一下原因。因为看起来提出问题的人已经安装了最新版本的 Cython。接受的答案表明问题是传递给 gcc 的包含路径
猜你喜欢
  • 2011-05-24
  • 1970-01-01
  • 2015-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-22
  • 1970-01-01
  • 2020-01-22
相关资源
最近更新 更多