windows下使用SWIG编译python模块

用C++对python加速是个不错的选择,但是python直接调用DLL写起来不是太容易,多亏了SWIG,使这项工作变得简单。

SWIG官网 

网上对SWIG的使用有些资料,但是直接使用SWIG自带的example介绍的很少, 虽然官网有Tutorial,但是也有些过时了。为此写这篇文章用于记录使用SWIG例子的步骤,另外还有写出错的解决办法。

使用的环境:

  • PC系统:win10
  • python 3.6 64bit
  • vs2010
  • swigwin-4.0.1

使用例子:\Examples\python\class

步骤:

1、去官网下载Window版SWIGhttp://prdownloads.sourceforge.net/swig/swigwin-4.0.1.zip

2、解压后,可看到里面有swig.exe程序。

3、设置环境变量,可参考 swigwin-4.0.1/Doc/Manual/Windows.html,下面是python的设置方法

PYTHON_INCLUDE : Set this to the directory that contains Python.h
PYTHON_LIB : Set this to the Python library including path for linking

Example using Python 2.1.1:
PYTHON_INCLUDE: D:\python21\include
PYTHON_LIB: D:\python21\libs\python21.lib

3、进入例子文件夹下,双击直接打开example.dsp(VS2010会将工程升级到新版本)

这里对工程稍作讲解:

工程属性中,可以看到要用到PYTHON_INCLUDE环境变量

windows下使用SWIG编译python模块

example.i右击 =>Custom build Tool => Command Line

可看到 example.i脚本 通过swig.exe程序编译,运行后会生成example_wrap.cxx和 example.py

windows下使用SWIG编译python模块

4、编译工程

编译失败:报错信息 c:\python3.6\include\pyport.h(6): fatal error C1083: Cannot open include file: 'inttypes.h': No such file or directory

找到解决方案 https://bugs.python.org/issue29244

Python 3.6 now requires inttypes.h on all platforms.  However, this is not provided by MSVC 2010 and 2012, which is still used by some people who build extension modules for Python.

MSVC 2010 does provide stdint.h, and replacing the inttypes.h include with an include to stdint.h seems to work fine.

I would suggest a fix along the lines of this:

#if defined(_MSC_VER) && _MSC_VER < 1800
#include <stdint.h>
#else
#include <inttypes.h>
#endif

Alternatively, the HAVE_INTTYPES_H definition could be used to fall back to stdint.h, and it could be undefined for the MSVC build.

再次编译尝试,报了一堆错误

1>     Creating library .\Release\_example.lib and object .\Release\_example.exp
1>example_wrap.obj : error LNK2019: unresolved external symbol __imp__PyUnicode_FromString referenced in function "struct _object * __cdecl SWIG_Python_str_FromChar(char const *)" ([email protected]@[email protected]@[email protected])
1>example_wrap.obj : error LNK2001: unresolved external symbol __imp__PyExc_RuntimeError
1>example_wrap.obj : error LNK2001: unresolved external symbol __imp__PyExc_AttributeError
1>example_wrap.obj : error LNK2001: unresolved external symbol __imp__PyExc_SystemError
1>example_wrap.obj : error LNK2001: unresolved external symbol __imp__PyExc_ValueError
1>example_wrap.obj : error LNK2001: unresolved external symbol __imp__PyExc_SyntaxError
1>example_wrap.obj : error LNK2001: unresolved external symbol __imp__PyExc_OverflowError
1>example_wrap.obj : error LNK2001: unresolved external symbol __imp__PyExc_ZeroDivisionError
1>example_wrap.obj : error LNK2001: unresolved external symbol __imp__PyExc_TypeError
1>example_wrap.obj : error LNK2001: unresolved external symbol __imp__PyExc_IndexError
1>example_wrap.obj : error LNK2001: unresolved external symbol __imp__PyExc_IOError
1>example_wrap.obj : error LNK2001: unresolved external symbol __imp__PyExc_MemoryError

解决办法:工程配置成x64 解决,应该是我使用的python是64位的,module设置成x64才能编译成功

5、测试

runme.py

由于python3版本的缘故,需要修改程序中 print 转换为 print()

运行后,打印结果如下:

Creating some objects:
    Created circle <example.Circle; proxy of <Swig Object of type 'Circle *' at 0x000002336E1899C0> >
    Created square <example.Square; proxy of <Swig Object of type 'Square *' at 0x000002336E189A20> >

A total of 2 shapes were created

Here is their current position:
    Circle = (20.000000, 30.000000)
    Square = (-10.000000, 5.000000)

Here are some properties of the shapes:
    <example.Circle; proxy of <Swig Object of type 'Circle *' at 0x000002336E1899C0> >
        area      =  314.1592653589793
        perimeter =  62.83185307179586
    <example.Square; proxy of <Swig Object of type 'Square *' at 0x000002336E189A20> >
        area      =  100.0
        perimeter =  40.0

Guess I'll clean up now
0 shapes remain
Goodbye

祝你好运!