使用Cython + MinGW构建独立应用程序
我正在尝试从Python代码构建一个独立的应用程序。目前这个程序只是一个“你好,世界”的简单示例。我用Cython把它编译成一个.c文件:
"c:\python34\scripts\cython.exe" --embed hello.py
这个步骤没问题。接下来,我尝试编译并链接生成的.c文件,命令如下:
"c:\mingw32\bin\gcc.exe" -I"c:\python34\include" -L"c:\python34\libs" -lpython34 -ohello.exe hello.c
但是这时我遇到了一堆链接错误:
...\cc7PmSei.o:hello.c:(.text+0xe9): 找不到引用 `_imp__PyTuple_New'
...\cc7PmSei.o:hello.c:(.text+0x130): 找不到引用 `_imp__PyBytes_FromStringAndSize'
...\cc7PmSei.o:hello.c:(.text+0x177): 找不到引用 `_imp__PyModule_Create2'
...
...\cc7PmSei.o:hello.c:(.text+0x12b7): 找不到引用 `_imp__PyUnicode_Decode'
...\cc7PmSei.o:hello.c:(.text+0x12dd): 找不到引用 `_imp__PyUnicode_FromStringAndSize'
...\cc7PmSei.o:hello.c:(.text+0x1303): 找不到引用 `_imp__PyBytes_FromStringAndSize'
.../libmingw32.a(main.o):main.c:.text.startup+0xa7): 找不到引用 `WinMain@16'
collect2.exe: error: ld returned 1 exit status
一些额外的信息:我使用的是64位的Windows 7家庭版操作系统,Python版本是32位的3.4.1,Cython版本是0.20.1,TDM-GCC版本是32位的4.7.1。
我做了一些研究。有些人说,这可能是因为使用了32位的C编译器和64位的Python,但我这里并不是这种情况。还有一些人提到我需要创建libpython34.a文件,但我的Python版本已经自带这个文件了。
有没有人知道我哪里出错了?谢谢大家。
3 个回答
在mingw-w64(来自win-builds.org的32位版本)中,gcc-4.8.1有一个叫做-municode的选项,这个选项会让程序使用wmain()作为入口点,同时支持UTF-16格式的命令行输入,能正常工作。可惜的是,官方文档里没有提到这个选项。我是在经过三天的实验后,在一些IRC聊天记录中发现的这个信息 :)
在hello.c文件中找到:
#if PY_MAJOR_VERSION < 3
int main(int argc, char** argv) {
#elif defined(WIN32) || defined(MS_WINDOWS)
int wmain(int argc, wchar_t **argv)
然后把wmain换成main。这对我有效。
好的,我搞明白了。这里有两个问题:
首先,出现“未定义的引用 'WinMain@16'”这个错误,是因为Cython为Python 3生成的是'wmain'而不是'main'。在MinGW中有一个'-municode'的命令行选项可以支持'wmain',但这个选项似乎只在最新的64位版本的MinGW中实现。我安装的MinGW 4.8.1是32位的,所以没有这个支持。一个替代方案是使用一个C语言的包装'main'函数,或者直接使用Python 2.7。我选择了后者。
剩下的未定义引用是因为参数的顺序不对。我可以用以下命令顺利构建这个应用程序:
"c:\mingw\bin\gcc.exe" -I"c:\python27\include" -L"c:\python27\libs" hello.c -ohello.exe -lpython27