【问题标题】:Building a Python C extension on Windows在 Windows 上构建 Python C 扩展
【发布时间】:2019-05-16 15:04:00
【问题描述】:

我正在尝试用 C 构建一个小型 Python 模块。它只是一个包含单个头文件并链接单个静态库的单个 .C 文件。

在 Linux 上一切正常,但我们的一名团队成员使用 Windows,所以我也想为 Windows 构建这个模块。

我正在使用安装了 Visual Studio Build Tools 2017 的 Windows 10,包括桌面版 VC++ 2015.3 v14.00 (v140) 工具集。我正在使用 Python 3.6。

from setuptools import setup, Extension

drone_logger_module = Extension('DroneLogger',
                                include_dirs=['Output\\include'],
                                libraries=['DroneLoggerWindows'],
                                library_dirs=['x64\\Release'],
                                sources=['Output\\src\\DroneLogger.py.c'])

setup([...],
      ext_modules=[drone_logger_module])

当我运行python setup.py bdist_wininst 时,我得到以下输出:

running bdist_wininst
running build
running build_ext
building 'DroneLogger' extension
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -IOutput\include -IC:\Users\piete\AppData\Local\Programs\Python\Python36\include -IC:\Users\piete\AppData\Local\Programs\Python\Python36\include "-IC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE" "-IC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\ATLMFC\INCLUDE" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\include\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\shared" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt" /TcOutput\src\DroneLogger.py.c /Fobuild\temp.win-amd64-3.6\Release\Output\src\DroneLogger.py.obj
DroneLogger.py.c
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\x86_amd64\link.exe /nologo /INCREMENTAL:NO /LTCG /DLL /MANIFEST:EMBED,ID=2 /MANIFESTUAC:NO /LIBPATH:x64\Release /LIBPATH:C:\Users\piete\AppData\Local\Programs\Python\Python36\libs /LIBPATH:C:\Users\piete\AppData\Local\Programs\Python\Python36\PCbuild\amd64 "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\LIB\amd64" "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\ATLMFC\LIB\amd64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\ucrt\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\lib\um\x64" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.17763.0\um\x64" DroneLoggerWindows.lib /EXPORT:PyInit_DroneLogger build\temp.win-amd64-3.6\Release\Output\src\DroneLogger.py.obj /OUT:build\lib.win-amd64-3.6\DroneLogger.cp36-win_amd64.pyd /IMPLIB:build\temp.win-amd64-3.6\Release\Output\src\DroneLogger.cp36-win_amd64.lib
DroneLogger.py.obj : warning LNK4197: export 'PyInit_DroneLogger' specified multiple times; using first specification
Creating library build\temp.win-amd64-3.6\Release\Output\src\DroneLogger.cp36-win_amd64.lib and object build\temp.win-amd64-3.6\Release\Output\src\DroneLogger.cp36-win_amd64.exp
Generating code
Finished generating code
LINK : fatal error LNK1158: cannot run 'rc.exe'
error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\x86_amd64\\link.exe' failed
with exit status 1158

然后我关注this SO answer,并将C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x64\rc.exercdll.dll 复制到C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\x86_amd64\。这解决了链接问题。

我花了几天时间试图让它在 Windows 上运行,但我想出的解决方案有点问题(也就是说,我不知道为什么它不能开箱即用,我有一种感觉,我不应该为了让它工作而移动 Microsoft EXE 和 DLL)。

我的问题有两个:

  • 真的没有更好/更简单的方法来为 Python C 扩展构建 Windows 安装程序吗?
  • 为什么这个解决方案有效,为什么有必要?

【问题讨论】:

  • 我希望它是一个 dll(或“pyd”)。但是对于构建,您可能会受益于其中一个批处理文件,该批处理文件使用路径和环境变量设置命令行 shell。例如,工具文件夹中的 VsDevCmd.bat 或 vsvars32.bat。
  • 我不确定我是否理解您的评论,您能详细说明一下吗?
  • 我是说 Visual Studio 通常与设置构建环境的脚本(.bat 文件)打包在一起。我的评论可能不适用于您的情况。

标签: python c windows pip setuptools


【解决方案1】:

在 Linux 上编译 Python 扩展通常比在 Windows 上更容易的原因是,通过 Linux 上的标准包管理,您通常会安装与编译 Python 本身相同的 C 编译器。在 Windows 上,您可以选择多个 Visual Studio 版本:mingw、cygwin。 对于 Windows,我发现使用特殊的 Visual C++ for Python 2.7 package from Microsoft 最直接,它与问题中使用的较新的 Visual Studio 版本不同,它在其路径中正确地包含了 rc.exe 以及 Visual C 编译器。 另一种解决方案是安装mingw 编译器并在主python 文件夹的Lib/distutils 中创建一个文件distutils.cfg,其中包含内容

[build]
compiler=mingw32

[build_ext]
compiler=mingw32

改为使用这些编译器。除非将 -static-libgcc(和用于 C++ 项目的 -static-libstdc++)添加到链接器标志中,否则 libgcc(和用于 libstdc++)的 DLL 必须随扩展一起提供,因此它也可以在没有安装 mingw 运行时/在路径中的情况下工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-04
    • 2020-11-11
    • 1970-01-01
    • 2020-06-02
    • 1970-01-01
    相关资源
    最近更新 更多