简体   繁体   English

如何在 Windows 上使用 MinGW-w64 创建 C 扩展/嵌入 Python

[英]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.pyxcython -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提供的信息:

  • Headers: We need the path to the Python includes.头:我们需要包含 Python 的路径。 For a way to find them see this SO-post .有关找到它们的方法,请参阅此SO-post
  • DLL: mingw-w64's linker works differently than MSVC's: python-dll and not python-lib is needed. DLL: mingw-w64 的 linker 的工作方式与 MSVC 不同:需要 python-dll 而不是python-lib。 So we need the path to the 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:重要的细节是:

  • it is probably Ok to use only use -O2 for optimization and leave <other_options> empty-可能只使用-O2进行优化并将<other_options>留空-
  • It is important to define 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):为了在 windows 上为 x64 构建,必须对其进行设置,但它仅适用于 MSVC (定义_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.

相关问题 如何使用 mingw-w64、Python 和 pybind11 手动构建 C++ 扩展? - How can I build manually C++ extension with mingw-w64, Python and pybind11? 如何构建 setup.py 以使用 Python、pybind11 和 Mingw-w64 编译 C++ 扩展? - How can I build a setup.py to compile C++ extension using Python, pybind11 and Mingw-w64? 如何在 Python 中使用 MinGW-w64 构建我的 C 扩展? - How can I build my C extensions with MinGW-w64 in Python? SQLite 使用 mingw-w64 编译扩展 Windows x64 - SQLite compiling extension Windows x64 with mingw-w64 调用MinGW-w64编译库的函数时,Windows的Python挂起 - Python for Windows hang while calling a function of MinGW-w64 compiled library 如何使用 pip 在 Windows 7 上使用 MinGW-w64 编译器安装软件包? - How to use pip to install packages using MinGW-w64 compiler on Windows 7? 绑定 C++ 和 Python 时,SWIG 在具有 MinGW-w64 的 Windows 上不起作用:导入时 DLL 加载失败:找不到指定的模块 - SWIG doesn't work on Windows with MinGW-w64 when binding C++ and Python: DLL load failed while importing: The specified module could not be found 如何在自己的 Python 包中结合自己的 C 扩展 - How to combine own C-extension in own Python Package 如何将 python c-extension 方法声明为类方法? - How to declare a python c-extension method as a classmethod? 使用MinGW-w64时如何解决cython中的“未定义引用错误”错误? - How can I solve "undefined reference error to" error in cython when using MinGW-w64?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM