[阅读: 806] 2008-01-13 07:40:24
			
				想要快一点的方法吗,使用swig吧。假设你有一些c你想再加入Tcl, Perl, Python, Java and C#.。举例来说有这么一个文件example.c
     /* File : example.c */
     
     #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);
     }
     
     
接口文件
现在,为了增加这些文件到你喜欢的语言中,你需要写一个接口文件(interface file)投入到swig中。这些C functions的接口文件可能如下所示:
     /* example.i */
     %module example
     %{
     /* Put header files here or function declarations like below */
     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();
     
建立Tcl模块
在UNIX系统提示,键入以下信息(LINUX系统请见SWIG WIKI共享库页面其他操作系统帮助):
     unix % swig -tcl example.i
     unix % gcc -fpic -c example.c example_wrap.c \
            -I/usr/local/include 
     unix % gcc -shared example.o example_wrap.o -o example.so
     unix % tclsh
     % load ./example.so example
     % puts $My_variable
     3.0
     % fact 5
     120
     % my_mod 7 3
     1
     % get_time
     Sun Feb 11 23:01:07 1996
     
     % 
     
该SWIG命令创建了一个文件example_wrap.c ,编辑并且和其余的程序联接。在这情况下,我们必须创建一个动态可装载的链接。能够装载进入TCL使用LOAD命令。
建立Python模块
转换编码C成Python模块很简单,只需要按如下做即可(请见其他操作系统的SWIG共享库帮助手册):
     
     unix % swig -python example.i
     unix % gcc -c example.c example_wrap.c \
            -I/usr/local/include/python2.1
     unix % ld -shared example.o example_wrap.o -o _example.so 
     
我们现在可以使用如下Python模块 :
     >>> import example
     >>> example.fact(5)
     120
     >>> example.my_mod(7,3)
     1
     >>> example.get_time()
     'Sun Feb 11 23:01:07 1996'
     >>>
     
建立Perl模块
你可以建立如下的Perl模块,如Solaris(请见其他操作系统的SWIG共享库帮助手册):
     unix % swig -perl5 example.i
     unix % gcc -c example.c example_wrap.c \
            `perl -MExtUtils::Embed -e ccopts`
     unix % ld -G example.o example_wrap.o -o example.so
     unix % perl
     use example;
     print $example::My_variable,"\n";
     print example::fact(5),"\n";
     print example::get_time(),"\n";
     <ctrl-d>
     3.0
     120
     Sun Feb 11 23:01:07 1996
     unix % 
     
建立Java模块
SWIG也会产生JNI代码以便Jave代码进入C/CC++。以下是建立一个Jave模块的事例(cygwin ,见其他操作系统的swig维基共享库页帮助):
     $ swig -java example.i
     $ gcc -c example.c example_wrap.c -I/c/jdk1.3.1/include -I/c/jdk1.3.1/include/win32
     $ gcc -shared example.o  example_wrap.o -mno-cygwin -Wl,--add-stdcall-alias  -o example.dll
     $ cat main.java
     public class main {
       public static void main(String argv[]) {
         System.loadLibrary("example");
         System.out.println(example.getMy_variable());
         System.out.println(example.fact(5));
         System.out.println(example.get_time());
       }
     }
     $ javac main.java
     $ java main
     3.0
     120
     Mon Mar  4 18:20:31  2002
     $
     
建立C#模块
SWIG也会产生代码以便C#使用Pinvoke进入C/CC++。以下是如何建立C#模块事例。cygwin ,见其他操作系统的swig维基共享库页帮助。使用了开源DotGNU Portable.NET能够在大多数Unix系统上运行,和其他C# compilers一样方便使用:
     $ swig -csharp  example.i
     $ gcc -c -fpic  example.c example_wrap.c
     $ gcc -shared example.o  example_wrap.o   -o libexample.so
     $ cscc -o runme *.cs
     $ cat runme.cs
     using System;
     public class runme {
         static void Main() {
             Console.WriteLine(example.My_variable);
             Console.WriteLine(example.fact(5));
             Console.WriteLine(example.get_time());
         }
     }
     $ ilrun runme
     3
     120
     Tue May 13 10:45:45 2003
     
     $
     
SWIG 懒人方法
如上所见,并非总是需要写一个专门的接口文件。如果你有一个头文件,你可以直接在其中包含SWIG接口,如例:
     %module example
     %{
     /* Includes the header in the wrapper code */
     #include "header.h"
     %}
     
     /* Parse the header file to generate wrappers */
     %include "header.h"
     
另外,有些人可能只包括SWIG条件指令在头文件中。例如:
     #ifdef SWIG
     %module example
     %{
     #include "header.h"
     %}
     #endif
     
     extern int fact(int n);
     ...
     
Microsoft Windows下运行SWIG
SWIG能够运行在所有已知的32位版本的WINDOWS下95/98/NT/2000/XP。SWIG通常使用命令提示符因此能够使用NMAKE。模块通常由DLL编译,可动态加载入Tcl, Python,或者任何你使用的语言。只需要小小加工,SWIG就能够在MS下发挥巨大作用。
That's it (well, more or less)
在开始前,你需要知道的事情。这里是简短的清单:
    * 明确模块名称
    * 使用 ANSI C/C++
    * 理解如何编写一个共享模块/动态连接库(可能需要阅读一些所使用的编译器的帮助文件)
    * 放松 
Surely there's more to it...
上述例子都很简单,但是大体思路已经延伸到复杂的C/C++。事实上,重要的是明白SWIG一个完整的C++支持下几乎能包含所有语言的特征。这些包括预处理,指针,类,甚至C++模块。SWIG能够在特定语言打包结构和类变成PROXY。
为了说明这一点,假设你想要封装以下C++数据结构:
     // pair.h.  A pair like the STL
     namespace std {
        template<class T1, class T2> struct pair {
            T1 first;
            T2 second;
            pair() : first(T1()), second(T2()) { };
            pair(const T1 &f, const T2 &s) : first(f), second(s) { }
        };
     }
     
为了封装SWIG你需要如下接口:
     // pair.i - SWIG interface
     %module pair
     %{
     #include "pair.h"
     %}
     
     // Ignore the default constructor
     %ignore std::pair::pair();      
     
     // Parse the original header file
     %include "pair.h"
     
     // Instantiate some templates
     
     %template(pairii) std::pair<int,int>;
     %template(pairdi) std::pair<double,int>;
     
接下去是编译(Python):
     $ swig -python -c++ pair.i
     $ c++ -c pair_wrap.c -I/usr/local/include/python2.1
     $ c++ -shared pair_wrap.o -o _pair.so
     $ python
     Python 2.1 (#3, Aug 20 2001, 15:41:42) 
     [GCC 2.95.2 19991024 (release)] on sunos5
     Type "copyright", "credits" or "license" for more information.
     >>> import pair
     >>> a = pair.pairii(3,4)
     >>> a.first
     3
     >>> a.second
     4
     >>> a.second = 16
     >>> a.second
     16
     >>> b = pair.pairdi(3.5,8)
     >>> b.first
     3.5
     >>> b.second
     8