下面具体介绍一下Swig的使用方法。刚才说了,swig和boost不一样,它不用对源代码进行破坏,只需要在外面多写一个接口文件。假设有如下的cpp文件需要封装:
<span style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; background: transparent;">#include <time.h>
double My_variable = 3.0;
int fact(int n) {
if (n <= 1) return 1;
else return n*fact(n-1);
}
int my_mod(int x, int y) {
return (x%y);
}
char *get_time()
{
time_t ltime;
time(<ime);
return ctime(<ime);
}</span>
那么我们需要写如下接口文件(example.i):
<span style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; background: transparent;"> %module example
%{
/* Put header files here or function declarations like below */
#define SWIG_FILE_WITH_INIT
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
%}
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();</span>
这是Python tutorial中的一个例子。下面将具体介绍一下example.i这个文件。
%module 后面的名字是被封装的模块名称。封装口,python通过这个名称加载程序。
%{ %}之间所添加的内容,一般包含此文件需要的一些函数声明和头文件。
最后一部分,声明了要封装的函数和变量。
比较建议的写法是,把要封装的函数声明部分写成头文件,假如为example.h,这样接口文件就非常简单了:
<span style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; background: transparent;"> %module example
%{
/* Put header files here or function declarations like below */
#define SWIG_FILE_WITH_INIT
#include"example.h"
%}
%include"example.h"</span>
为了编译出一个封装的动态库,依次执行:
<span style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; background: transparent;"> $ swig -python -c++ example.i
$ g++ -c -fPIC example_wrap.cxx -I/usr/local/include/python2.6
$ g++ -shared example_wrap.o -o _example.so</span>
第一步的过程会生成example_wrap.cxx的文件。因为现在是cpp文件,所以编译出来是个.cxx文件和一个example_wrap.py。如果是c的文件,编译后会出现一个.c的文件。这个文件相当于将原cpp文件进行了封装,wrap了一层。后面两步就是标准的生成动态链接库的步骤了。这样得到的动态链接库就可以直接被python import了。
<span style="margin: 0px; padding: 0px; border: 0px; font-size: 14px; background: transparent;"> >>> import example
>>> example.fact(5)
120
>>> example.my_mod(7,3)
1
>>> example.get_time()
'Tue Dec 11 23:01:07 2012'
>>></span>