SWIG是个帮助使用C或者C++编写的软件能与其它各种高级编程语言进行嵌入联接的开发工具。SWIG能应用于各种不同类型的语言包括常用脚本编译语言例如Perl, PHP, Python, Tcl, Ruby and PHP。

其中关于mac下的一些特殊用法参考了这个blog

1. 首先写一个最简单的C程序:

1
2
3
int add(int a, int b){
return a+b;
}

2. 再写一个Swig接口文件:

1
2
3
4
5
6
//func.i
%module func
%{
extern int add(int, int);
%}
extern int add(int, int);

3. 编译func.c得到目标文件func.o:

1
gcc -c -fpic func.c

4. 由接口文件func.i生成func_wrap.c和func.py:

1
swig -python func.i

如果是C++,记得加上-c++参数。

5. 编译接口:

编译需要用到Python.h头文件,那么在macOS下的Python.h文件在哪呢,具体跟macOS和Xcode版本有关,以MacOSX10.12为例,具体路径在/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7

为了以后使用方便,加一个链接到系统include目录:

1
ln -s /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 /usr/local/include/python2.7

然后编译接口:

1
gcc -c -fpic func_wrap.c -I/usr/include/python2.7

6. 链接目标文件,生成_func.so:

1
gcc -shared -lpython2.7 func.o func_wrap.o -o _func.so

注意这里需要指定链接的Python版本,用-lpython2.7参数。

7. 最后在在python中import测试:

1
2
import func
print(func.add(2,7))

这时候会出现一个强力的bug:Fatal Python error: PyThreadState_Get: no current thread,经过不断查找与测试,最终发现是因为brew安装的python出的差错(看这里,即使用自带的头文件编译一样没有用,真是好坑,先后被brew的python 2.7和3.5都坑过了,还是brew remove python卸掉比较安全放心。