2.3 一个示例
演示SWIG的最好方法是提供一个简单的例子。考虑如下代码:
/* File : example.c */double My_variable = 3.0;/* Compute factorial of n */int fact(int n) {if (n <= 1) return 1;else return n*fact(n-1);}/* Compute n mod m */int my_mod(int n, int m) {return(n % m);}
假设你想从Tcl中访问这些函数和全局变量。你可以想下面这样,从编写一个SWIG接口文件开始(按照惯例,这些文件以.i为后缀)。
2.3.1 SWIG接口文件
/* File : example.i */%module example%{/* Put headers and other declarations here */extern double My_variable;extern int fact(int);extern int my_mod(int n, int m);%}extern double My_variable;extern int fact(int);extern int my_mod(int n, int m);
接口文件中包含了ANSI C 函数原型和变量声明。%module指令为SWIG生成的模块定义了模块名。 %{ %}块提供插入代码的位置,可以插入C语言头文件或其他C声明到生成的包装代码中。
2.3.2 swig命令
SWIG提供了swig命令行程序。我们可以使用它像下面这样构建一个Tcl模块(Linux系统下):
unix > swig -tcl example.iunix > gcc -c -fpic example.c example_wrap.c -I/usr/local/includeunix > gcc -shared example.o example_wrap.o -o example.sounix > tclsh% load ./example.so% fact 424% my_mod 23 72% expr $My_variable + 4.57.5%
swig命令产生一个新的文件example_wrap.c,他需要和example.c文件一起编译。绝大多数的操作系统和脚本语言现在都提供动态库支持。在我们的这个例子中,Tcl模块被编译成一个共享库。当加载后,Tcl可以访问SWIG接口文件中声明的函数及全局变量。看看生成的example_wrap.c,会发现里面乱七八糟的。但是不用担心。
2.3.3 构建Perl5模块
现在,让我们让这些功能用于Perl5模块。不作任何更改,请键入以下内容(Solaris系统):
unix > swig -perl5 example.iunix > gcc -c example.c example_wrap.c \-I/usr/local/lib/perl5/sun4-solaris/5.003/COREunix > ld -G example.o example_wrap.o -o example.so # This is for Solarisunix > perl5.003use example;print example::fact(4), "\n";print example::my_mod(23,7), "\n";print $example::My_variable + 4.5, "\n";<ctrl-d>2427.5unix >
2.3.4 构建Python模块
最后,让我们构建一个Python模块(Irix系统):
unix > swig -python example.iunix > gcc -c -fpic example.c example_wrap.c -I/usr/local/include/python2.0unix > gcc -shared example.o example_wrap.o -o _example.sounix > pythonPython 2.0 (#6, Feb 21 2001, 13:29:45)[GCC egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)] on linux2Type "copyright", "credits" or "license" for more information.>>> import example>>> example.fact(4)24>>> example.my_mod(23,7)2>>> example.cvar.My_variable + 4.57.5
2.3.5 快捷方法
对那些比较懒的程序员,他们想知道为什么我们需要提供额外的接口文件呢。结果可以证明,一般你可以不需要提供它。例如,为构建一个Perl5模块,你可以直接使用C头文件,像下面这样提供一个模块名字:
unix > swig -perl5 -module example example.hunix > gcc -c example.c example_wrap.c \-I/usr/local/lib/perl5/sun4-solaris/5.003/COREunix > ld -G example.o example_wrap.o -o example.sounix > perl5.003use example;print example::fact(4), "\n";print example::my_mod(23,7), "\n";print $example::My_variable + 4.5, "\n";<ctrl-d>2427.5
