对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

#include "temp.h"

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
7
def 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
SWIGINTERN PyObject *_wrap_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
int arg1 ;
int arg2 ;
int val1 ;
int ecode1 = 0 ;
int val2 ;
int ecode2 = 0 ;
PyObject * obj0 = 0 ;
PyObject * obj1 = 0 ;
int result;

if (!PyArg_ParseTuple(args,(char *)"OO:add",&obj0,&obj1)) SWIG_fail;
ecode1 = SWIG_AsVal_int(obj0, &val1);
if (!SWIG_IsOK(ecode1)) {
SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "add" "', argument " "1"" of type '" "int""'");
}
arg1 = static_cast< int >(val1);
ecode2 = SWIG_AsVal_int(obj1, &val2);
if (!SWIG_IsOK(ecode2)) {
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "add" "', argument " "2"" of type '" "int""'");
}
arg2 = static_cast< int >(val2);
result = (int)add(arg1,arg2);
resultobj = SWIG_From_int(static_cast< int >(result));
return resultobj;
fail:
return NULL;
}

由于在python中所有的数据包括int, float这种基本数据类型也都是用PyObject来实现的,因此swig要做的数据转换就是PyObject <–> int等数据之间的转换,数据转换好以后就可以在封装函数内直接调用C++的函数了。我特地做了个图:

可见所谓函数封装也就是给真正的内部函数套一个壳子,壳子的主要作用是数据转换工作(传入参数和返回值的操作)。这样我们在python中调用C++函数实际上就是操作壳子中的C/C++函数。

Comments