[英]How to create C-extension/embed Python with MinGW-w64 on Windows
Is it possible (and how) to use MinGW-w64 for building of C-extensions for Python or embeding Python on Windows?是否可以(以及如何)使用 MinGW-w64 为 Python 构建 C 扩展或在 Windows 上嵌入 Python?
Let's take as example the following cython-extension foo.pyx
:让我们以以下 cython-extension
foo.pyx
:
print("foo loaded")
from which the C-code can be generated either via cython -3 foo.pyx
or cython -3 --embed foo.pyx
if interpreter should be embedded.如果应该嵌入解释器,可以通过
cython -3 foo.pyx
或cython -3 --embed foo.pyx
生成 C 代码。
While mingw-w64
-compiler is not really supported (the only supported windows compiler is MSVC ), it can be used to create C-extensions or to embed Python.虽然并不真正支持
mingw-w64
-compiler(唯一支持的 windows 编译器是MSVC ),但它可用于创建 C 扩展或嵌入 Python。 There are however no guarantee, this won't break in the future versions.但是不能保证,这不会在未来的版本中中断。
distutils
does not support mingw-w64
, so there is no gain in setting up a setup.py-file - the steps must be performed manually. distutils
不支持mingw-w64
,因此设置 setup.py 文件没有任何好处 - 必须手动执行这些步骤。
First we need some information usually provided by distutils
:首先,我们需要一些通常由
distutils
提供的信息:
pythonXY.dll
which is usually next the the python.exe
.pythonXY.dll
的路径,它通常在python.exe
旁边。 Once the C-code is created/generated, the extension can be build via创建/生成 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
The important details are:重要的细节是:
-O2
for optimization and leave <other_options>
empty--O2
进行优化并将<other_options>
留空-MS_WIN64
-macro (eg via -DMS_WIN64
).MS_WIN64
-macro(例如通过-DMS_WIN64
)很重要。 In order to build for x64 on windows it must be set, but it works out of the box only for MSVC (defining _WIN64
could have slightly different outcomes):_WIN64
可能会产生略微不同的结果):#ifdef _WIN64
#define MS_WIN64
#endif
if it is not done, at least for files generated by Cython the following error message will be generated by the compiler:如果未完成,至少对于 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
is just a dll in disguise, thus we need the -shared
option, which means a dynamic library (ie shared-object in Linux-world) will be created. pyd
只是一个伪装的-shared
,因此我们需要 -shared 选项,这意味着将创建一个动态库(即 Linux 世界中的共享对象)。
It is important, that the python-library ( pythonXY
) should be the dll itself and not the lib
(see this SO-post ).重要的是,python 库(
pythonXY
)应该是 dll 本身而不是lib
(请参阅此SO-post )。 Thua we use the path to pythonXY.dll
(in my case python37) and not pythonXY.lib
, as it would be the case for MSVC.我们使用
pythonXY.dll
的路径(在我的情况下是 python37)而不是pythonXY.lib
,因为它是 MSVC 的情况。
One probably should add the proper suffix to the resulting pyd-file, I use the old convention for simplicity here.可能应该在生成的 pyd 文件中添加正确的后缀,为了简单起见,我在这里使用旧约定。
Embeded Python:嵌入 Python:
In this case an executable should be build (eg the C-file is generated by Cython with --embed
option: cython -3 --embed foo.pyx
) and thus the command line looks as follows:在这种情况下,应该构建一个可执行文件(例如,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
There are two important differences:有两个重要的区别:
-shared
should no longer be used, as the result is no longer a dynamic library (that is what *.pyd-file is after all) but an executable. -shared
不应再使用,因为结果不再是动态库(毕竟 *.pyd-file 就是这样),而是可执行文件。-municode
is needed, because for Windows, Cython defines int wmain(int argc, wchar_t **argv)
instead of int main(int argc, char** argv)
. -municode
是必需的,因为对于 Windows,Cython 定义int wmain(int argc, wchar_t **argv)
而不是int main(int argc, char** argv)
。 Without this option, an error message like/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
would appear (see this SO-post for more information).会出现(有关更多信息,请参阅此SO-post )。
Note: for the resulting executable to run, a whole python-distribution (and not only the dll) is needed (see also this SO-post ), otherwise the resulting executable will abort with error (either the python dll wasn't found or the python installation or the site packages - depending on the configuration of the machine on which the exe has to run).注意:要运行生成的可执行文件,需要完整的 python 分发(而不仅仅是 dll)(另请参见此SO-post ),否则生成的可执行文件将因错误而中止(未找到 python dll 或python 安装或站点包 - 取决于必须运行 exe 的机器的配置)。
mingw-w64
can also be used on Linux for cross-compilation for Windows, see this SO-post . mingw-w64
也可以在 Linux 上用于 Windows 的交叉编译,请参阅此SO-post 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.