初探SWIG对函数的封装
对swig对C/C++函数的封装原理进行了初步的学习(内容很少,主要是避免让我写代码的时候陷入强迫症的苦恼。
看到KMCLib中在python中直接使用c++的函数,不禁又让我开始联想这是为什么,于是我就自己写个小测试看看swig是怎么封装函数的。
先定义两个C++函数:1
2
3
4
5// file: temp.h
int add(int a, int b);
double showg();
函数实现文件:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// file: temp.cpp
int add(int a, int b)
{
return a + b;
}
static double g = 10.0;
double showg()
{
return g;
}
开始用swig进行封装:1
2
3$ swig -python -c++ -verbose temp.i
$ g++ -shared -fPIC temp.cpp temp_wrap.cxx -o _temp.so
ok,这个程序能在python中执行,我现在想看swig是怎么封装这两个函数的。
先看看python直接调用的py模块文件中的代码,找到add和showg函数的定义:1
2
3
4
5
6
7def add(a, b):
return _temp.add(a, b)
add = _temp.add
def showg():
return _temp.showg()
showg = _temp.showg
可见他们都是将_temp模块中的相应的函数进行了封装或者说代理。那么python调用的应该是封装过以后的c++函数,毕竟python不可能直接调用C++函数(不然为什么要封装。。。
在temp_wrap.cpp中可以找到swig对两个原始C++函数的封装函数,通过封装,能够将传入的python数据转换成C++的数据类型并调用真正的C++函数返回C++数据,在将C++数据转换成python相应的数据。
1 | SWIGINTERN PyObject *_wrap_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { |
由于在python中所有的数据包括int
, float
这种基本数据类型也都是用PyObject
来实现的,因此swig要做的数据转换就是PyObject
<–> int
等数据之间的转换,数据转换好以后就可以在封装函数内直接调用C++的函数了。我特地做了个图:
可见所谓函数封装也就是给真正的内部函数套一个壳子,壳子的主要作用是数据转换工作(传入参数和返回值的操作)。这样我们在python中调用C++函数实际上就是操作壳子中的C/C++函数。