SWIG image
主页 |  开发 |  邮件列表 |  错误报告和补丁
Information
SWIG是什么
兼容性
特征
使用教程
文档
风险
历史
版本
参与者
项目
版权申明
相关链接
下载
SwigWiki
Exits
AllegroCL
C# - Mono
C# - MS .NET
CFFI
CHICKEN
CLISP
Guile
Java
Lua
MzScheme
Ocaml
Perl
PHP
Python
R
Ruby
Tcl/Tk
Our Generous Host
SourceForge logo

Tutorial

想要快一点的方法吗,使用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(&ltime);
     return ctime(&ltime);
 }
 
 

接口文件

现在,为了增加这些文件到你喜欢的语言中,你需要写一个接口文件(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
 

有什么问题可以通过swig-devel邮件列表进行反馈 .

最后修改: Thu Sep 27 21:25:53 2007