如何在Windows上使用MinGW-W64创建C扩展/嵌入Python [英] How to create C-extension/embed Python with MinGW-w64 on Windows

查看:24
本文介绍了如何在Windows上使用MinGW-W64创建C扩展/嵌入Python的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以(以及如何)使用MinGW-W64在Windows上构建Python的C扩展或嵌入Python?

让我们以以下cython扩展foo.pyx为例:

print("foo loaded")

如果应该嵌入解释器,则可以通过cython -3 foo.pyxcython -3 --embed foo.pyx从中生成C代码。

推荐答案

虽然并不真正支持mingw-w64-编译器(唯一支持的Windows编译器是MSVC),但它可以用于创建C扩展或嵌入Python.但是不能保证,这在将来的版本中不会中断。

distutils不支持mingw-w64,因此设置setup.py文件没有任何好处-这些步骤必须手动执行。

首先我们需要一些通常由distutils提供的信息:

  • Headers:我们需要指向Python Includes的路径。有关查找它们的方法,请参阅SO-post
  • dll:mingw-w64的链接器与MSVC的链接器的工作方式不同:需要使用python-dll和notpython-lib。因此,我们需要指向pythonXY.dll的路径,该路径通常位于python.exe旁边。

创建/生成C代码后,可以通过

构建扩展
x86_64-w64-mingw32-gcc -shared foo.c -DMS_WIN64 -O2 <other_options> -I <path_to_python_include> -L <path_to_python_dll> -lpython37 -o foo.pyd

重要细节如下:

  • 只使用-O2进行优化,将<other_options>留空-
  • 可能是可以的
  • 重要的是定义MS_WIN64-宏(例如通过-DMS_WIN64)。为了在Windows上构建x64,必须设置它,但它只能开箱即用for MSVC(定义_WIN64可能会有略微不同的结果):
#ifdef _WIN64
#define MS_WIN64
#endif

如果不这样做,至少对于Cython生成的文件,编译器将生成以下错误消息:

 error: enumerator value for ‘__pyx_check_sizeof_voidp’ is not an integer constant
  201 |     enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) };
  • pyd只是一个伪装的DLL,所以我们需要-shared选项,这意味着将创建一个动态库(即Linux世界中的共享对象)。

  • 重要的是,python库(pythonXY)应该是DLL本身,而不是lib(参见SO-post)。我们使用指向pythonXY.dll(在我的例子中是python37)的路径,而不是指向pythonXY.lib的路径,就像MSVC的情况一样。

您可能应该向生成的PYD文件添加适当的后缀,为简单起见,我在这里使用旧的约定。


嵌入式Python:

在这种情况下,应该生成一个可执行文件(例如,C文件是由Cython使用--embed选项:cython -3 --embed foo.pyx生成的),因此命令行如下所示:

x86_64-w64-mingw32-gcc foo.c -DMS_WIN64 -O2 <other_options> -I <path_to_python_include> -L <path_to_python_dll> -lpython37 -o foo.exe -municode

有两个重要区别:

  • 不应再使用-shared,因为结果不再是动态库(这毕竟是*.pyd-file),而是可执行文件。
  • -municode是必需的,因为对于Windows,Cython定义的是int wmain(int argc, wchar_t **argv),而不是int main(int argc, char** argv)。如果没有此选项,则会出现类似
  • 的错误消息
/build/mingw-w64-_1w3Xm/mingw-w64-4.0.4/mingw-w64-crt/crt/crt0_c.c:18: undefined reference to 'WinMain'
collect2: error: ld returned 1 exit status

将出现(有关详细信息,请参阅此SO-post)。

注意:要运行生成的可执行文件,需要完整的python分发(不仅是dll)(另请参阅SO-post),否则生成的可执行文件将中止,并返回错误(找不到pythondll,或者是python安装包或站点包-取决于必须运行exe的计算机的配置)。


mingw-w64也可以在Linux上用于Windows的交叉编译,请参阅SO-post

这篇关于如何在Windows上使用MinGW-W64创建C扩展/嵌入Python的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆