gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 14:17:10 24 4
gpt4 key购买 nike

我正试图使用distutils模块在Linux for Windows(mingw32)上交叉编译一个简单的SWIG Python扩展。
最终目标是为某些库编译一个python包装器,并能够在windows上使用它。显然,我从最基本的例子开始,不幸的是失败了。
以下是我正在使用的文件:
示例C

/* File : example.c */

/* A global variable */
double Foo = 3.0;

/* Compute the greatest common divisor of positive integers */
int gcd(int x, int y) {
int g;
g = y;
while (x > 0) {
g = x;
x = y % x;
y = g;
}
return g;
}

示例.i-swig接口文件
/* File : example.i */
%module example

%inline %{
extern int gcd(int x, int y);
extern double Foo;
%}

安装程序.py
# setup.py
import distutils
from distutils.core import setup, Extension

setup(name = "SWIG example",
version = "1.0",
ext_modules = [Extension("_example", ["example.i","example.c"])])

为了使用本机(Linux)GCC编译器进行编译,我调用:
python setup.py build

一切都有魅力!很遗憾,在尝试指定Windows目标时:
python setup.py build --compiler=mingw32

我得到的错误是gcc无法识别-mdll开关:
running build
running build_ext
building '_example' extension
swigging example.i to example_wrap.c
swig -python -o example_wrap.c example.i
creating build
creating build/temp.linux-x86_64-2.7
gcc -mdll -O -Wall -I/home/jojek/anaconda/include/python2.7 -c example_wrap.c -o build/temp.linux-x86_64-2.7/example_wrap.o
gcc: error: unrecognized command line option ‘-mdll’
error: command 'gcc' failed with exit status 1

公平地说,这是完全合理的,因为工具链是无效的。我确保 mingw32安装在我的机器上通过调用 dpkg -L mingw32我知道编译器位于 /usr/bin/i586-mingw32msvc-gcc中。
我的下一步是用编译器的实际路径重写CC环境变量当我再次尝试编译它时,会出现以下错误,其中缺少 sys/select.h头文件:
running build
running build_ext
building '_example' extension
swigging example.i to example_wrap.c
swig -python -o example_wrap.c example.i
creating build
creating build/temp.linux-x86_64-2.7
/usr/bin/i586-mingw32msvc-gcc -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/home/jojek/anaconda/include/python2.7 -c example_wrap.c -o build/temp.linux-x86_64-2.7/example_wrap.o
example_wrap.c:1: warning: -fPIC ignored for target (all code is position independent)
In file included from /home/jojek/anaconda/include/python2.7/Python.h:58,
from example_wrap.c:125:
/home/jojek/anaconda/include/python2.7/pyport.h:351:24: error: sys/select.h: No such file or directory
error: command '/usr/bin/i586-mingw32msvc-gcc' failed with exit status 1

有人知道如何管理这项任务吗?

最佳答案

在使用distutils编译Python模块时,会有很多幕后操作你在问题中的每一次尝试都越来越接近了,但是你现在遇到的问题是你在windows(cross)编译器中使用的是linux头文件。(sys/select.h isn't supported with mingw32,但cygwin可能是另一个故事)。实际上,正是由于缺少配置头文件,导致交叉编译尝试使用posix接口而不是win32替代接口。
我的答案是倒转几个步骤,开始简单地手工构建模块,在linux上使用mingw32,然后在证明我们拥有所需的一切之后,我们将使用distutils。
我还假设您没有一个windows构建框(甚至vm)可以简单地在windows上本地构建扩展,因为这比交叉编译简单得多。如果您正在阅读本文,并且可以选择使用windows框来构建windows python扩展,那么可以这样做,从而节省时间和精力。也就是说,只使用一个Linux框就可以构建Windows-Python模块。
从已经安装的mingw32开始,在Linux上运行(例如使用Debian/Ubuntu包),第一步是获取Windows头文件(或者更具体的配置)我假设你的目标是大多数人在搜索引擎中输入“python windows”时得到的版本,所以我从python.org下载了WindowsMSI安装程序并从中提取了它们。
我们希望从python发行版中获得两件事:
python27.dll(通常放在C:\windows\system32或C:\windows\syswow64中)
“include”目录(通常放在c:\ python27\include中)
在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中所有导出的符号,并让dll tool生成一个存根库,供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模块(它运行精细的跨平台)复制该工具的功能,以提取我们关心的导出,如果您希望避免使用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文件中提取的内容。
(这是我的 pefile
一旦获得了.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

在那里,我们有一个windows python模块,只使用linux构建。
要检查它是否真正运行,我将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能够找到正确的include文件和库,通过操纵其路径来进行链接。

关于python - 尝试使用distutils交叉编译mingw32的SWIG Python扩展时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32361119/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com