可能大家不是很熟悉swig这个名字,它的全称是Simple Wrapper and Interface Generator.它是干什么用的呢?是用来把C语言子程序包装成一些脚本语言的命令用的.比如,不少人喜欢使用Tcl/Tk来写点界面,但Tcl/Tk的数学功能实在太差,有时候就想自己给它扩充一些数学函数.又比如说,用Perl写个CGI程序,想用一个已经现成的自己编好的C语言子程序来处理用户返回的数据.这时候就用得上swig了.
其实刚才举的那些脚本语言都有自己的扩充接口,比如Perl有XS格式,Tcl/Tk有一套扩充内核用的C语言函数库.例如,要给Tcl扩充一个myfract命令,用来实现阶乘,可以这样做:
(1)写一个C语言程序,假设叫做fract.c,内容如下:
#include "tcl.h"
int Tcl_myfract(ClientData notUsed, Tcl_Interp interp, int argc, char
{
int i, j;
double res=1.0;
char re[30];
if (argc > 2)
{
Tcl_AppendResult(interp, "wrong args: should be myfract
return TCL_ERROR;
}
if (Tcl_GetInt(interp, argv[1], &i) != TCL_OK)
{
return TCL_ERROR;
}
for (j=1;j<=i;j++)
res = j;
sprintf(re,"%le",res);
Tcl_SetResult(interp, re, TCL_VOLATILE);
return TCL_OK;
}
int Fract_Init(Tcl_Interp Interp) {
Tcl_CreateCommand (Interp, "myfract", Tcl_myfract, (ClientData)
return TCL_OK;
}
(2)运行以下命令:
gcc -c fract.c
gcc -shared -o fract.so fract.o
生成fract.so动态连接库
(3)在tcl程序中加上"load ./fract.so"一句话,就可以用myfract命令了.
这种做法可以实现Tcl/Tk的任意扩充,功能强大,但实在是太麻烦了.而且,如果又想扩充Perl,Python等,那又得用它们的接口重写一遍.swig可以提供比较方便的统一扩充接口,而不需要对各种语言的特点有所了解,所以在很多情况下很适合使用.
下面我们看看swig怎样完成刚才的工作.
(1)写一个C语言函数提供阶乘功能,例如写一个fract.c,内容为:
double myfract(int n)
{
double res=1.0;
int j;
for (j=1;j<=n;j++)
res = j;
return(res);
}
(2)写一个通用接口文件,后缀为.i,例如fract.i,内容为:
%module myfract
extern double myfract(int);
第一句的意思是生成的模块叫myfract,第二句就是按C语言格式声明要输出的函数,加上一个extern.
(3)运行swig -tcl fract.i,生成fract_wrap.c和fract_wrap.c(自动生成的文档)
(4)运行
gcc -c fract.c fract_wrap.c
gcc -ltcl -shared -o myfract.so fract.o fract_wrap.o
生成myfract.so
(5)在Tcl程序中加上"load ./myfract.so"即可.
显然比刚才的办法好懂多了.
如果要生成的是Perl模块,那么第三步改成"swig -perl fract.i",这时还会生成一个myfract.pm文件.运行第四步时,前一个命令要改成:
gcc -c fract.c fract_wrap.c -I/usr/lib/perl5/i586-linux/5.00404/CORE/ -Dbool=char
其中的路径是perl.h所在的目录,每台机器可能不一样.最后在Perl程序中加上"use myfract"即可.
swig的功能其实很强大,它可以分析C/C++源程序,可以生成HTML/LaTex/text文档,等等.大家可以看它的文档(很多的pdf文件).就说这些.