您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

尝试使用distutils交叉编译mingw32的SWIG Python扩展时出错

尝试使用distutils交叉编译mingw32的SWIG Python扩展时出错

使用distutils编译python模块时,幕后有很多事情发生。您对问题的每次尝试都越来越接近,但是现在遇到的问题是,您正在使用带有Windows(交叉)编译器的Linux头文件。(mingw32不支持sys / select.h,但是cygwin可能是另一回事了)。实际上,是由于缺少配置头文件,导致您的交叉编译尝试使用POSIX接口而不是Win32替代方案。

我的回答倒退了几步,开始只是简单地手工构建模块,在Linux上使用mingw32,然后在证明我们具备所有要求之后,将开始使用distutils。

我还假设您没有Windows构建框(甚至是VM)可用于仅在Windows上本机构建扩展,因为这比交叉编译要简单得多。如果您正在阅读本文,并且可以选择使用Windows框来构建Windows Python扩展,请执行此操作,以节省时间和精力。也就是说,仅使用Linux盒即可构建Windows python模块

从已经安装并在Linux机器上工作的mingw32开始(例如使用Debian / Ubuntu软件包),第一步是获取Windows头文件(或更具体的配置)。我假设您的目标是大多数人在搜索引擎中键入“ python windows”时获得的构建,所以我从python.org下载Windows MSI安装程序并从中提取它们。

我们想从Python发行版中获得两件事:

在Linux下,有几种不同的方法可以解压缩。您可以使用Wine安装MSI文件。我在测试中成功使用了cabextract和7z,例如,使用cabextract:

cabextract /tmp/python-2.7.10.msi -F '*.h'
cabextract /tmp/python-2.7.10.msi -F 'python27.dll'

(注意:如果使用7z,则会在另一个名为“ python”的内部存档中找到您真正想要的文件)。

在这一点上,您还可以提取文件“ libpython27.a”,该文件通常位于c:\ python27 \ libs \中,但是此文件对于使用mingw32进行链接是不够的,甚至不起作用。

给定头文件,我们现在有足够的能力来编译扩展程序,尽管如上所述,要使mingw32链接到python27.dll,我们需要首先做更多的工作。我们将需要一个名为pexports的工具来列出Python DLL中所有导出的符号,并让dlltool生成存根库供mingw32链接。我直接下载了pexports,然后使用以下命令将其解压缩:

tar xvf ~/Downloads/pexports-0.47-mingw32-bin.tar.xz

解压缩后,我们将获得一个Windows可执行文件。我在这里的示例中使用Wine来直接运行它;或者,您可以提取源,并将其构建为可在Linux主机上本地运行的工具:

tar xvf ~/Downloads/pexports-0.47-mingw32-src.tar.xz
(cd pexports-0.47 && ./configure && make)

或者您也可以使用python模块pefile(在良好的跨平台上运行)复制该工具的功能,以提取我们关心的导出,如果您也希望避免使用Wine的话。

无论如何,使用pexports都可以生成一个.def文件,其中包含我们需要的dlltool信息:

wine bin/pexports.exe -v python27.dll > python27.def

或者,(如果您已将pexports构建为本机工具),则只需:

./pexports-0.47/pexports -v python27.dll > python27.def

python27.dll是我们之前从.msi文件提取文件

(这是我的pexports参考

获得.def文件后,您可以使用mingw32 dlltool生成一个.a文件,稍后我们将使用该文件python模块链接到:

i586-mingw32msvc-dlltool -A --dllname python27.dll --def python27.def --output-lib libpython27.a

现在,我们可以考虑运行SWIG本身来生成要编译的代码了。我将您的示例界面进一步简化为:

%module test

%inline %{
int gcd(int x, int y) {
  int g;
  g = y;
  while (x > 0) {
    g = x;
    x = y % x;
    y = g;
  }
  return g;
}
%}

然后在Linux机器上以以下方式运行SWIG:

swig -Wall -python test.i

生成了我用以下代码编译的test_wrap.c:

i586-mingw32msvc-gcc test_wrap.c -I../include -Wall -Wextra -shared -o _test.pyd ./libpython27.a

这里有一个仅使用Linux构建的Windows python模块

为了检查它是否真正运行,我将test.py和_test.pyd复制到Windows框中,然后执行以下操作:

Python 2.7.10 (default, May 23 2015, 09:40:32) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> test.gcd(1024, 512)
512
>>>

现在剩下的就是确保distutils可以通过操纵路径来找到正确的包含文件和库来进行链接

python 2022/1/1 18:45:10 有322人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶