Swig Tutorial
- 1. 想要快一点的方法吗, 使用 swig 吧。假设你有一些 c 你想再加入 Tcl, Perl, Python,
Java and C#.。举例来说有这么一个文件 example.c
1 /* File : example.c */
2
3 #include <time.h>
4
5 double My_variable = 3.0;
6
7 int fact(int n) {
8 if (n <= 1) return 1;
9 else return n*fact(n-1);
10 }
11
12 int my_mod(int x, int y) {
13
14 return (x%y);
15
16 }
17
18 char *get_time()
19 {
20
21 time_t ltime;
22
23 time(<ime);
24
25 return ctime(<ime);
26
27 }
28
29
接口文件
现在,为了增加这些文件到你喜欢的语言中, 你需要写一个接口文件(interface file)
投入到 swig 中。这些 C functions 的接口文件可能如下所示:
- 2. 1 /* example.i */
2
3 %module example
4
5 %{
6
7 /* Put header files here or function declarations like below */
8
9 extern double My_variable;
10
11 extern int fact(int n);
12
13 extern int my_mod(int x, int y);
14
15 extern char *get_time();
16
17 %}
18
19 extern double My_variable;
20
21 extern int fact(int n);
22
23 extern int my_mod(int x, int y);
24
25 extern char *get_time();
26
建立 Tcl 模块
在 UNIX 系统提示,键入以下信息(LINUX 系统请见 SWIG WIKI 共享库页面其他
操作系统帮助):
1 unix % swig -tcl example.i
2
3 unix % gcc -fpic -c example.c example_wrap.c
4
5 -I/usr/local/include
6
7 unix % gcc -shared example.o example_wrap.o -o example.so
- 3. 8
9 unix % tclsh
10
11 % load ./example.so example
12
13 % puts $My_variable
14
15 3.0
16
17 % fact 5
18
19 120
20
21 % my_mod 7 3
22
23 1
24
25 % get_time
26
27 Sun Feb 11 23:01:07 1996
28
29 %
该 SWIG 命令创建了一个文件 example_wrap.c,编辑并且和其余的程序联接。在
这情况下,我们必须创建一个动态可装载的链接。能够装载进入 TCL 使用 LOAD
命令。
建立 Python 模块
转换编码 C 成 Python 模块很简单,只需要按如下做即可(请见 SWIG Wiki Shared
Libraries(SWIG 共享帮助手册其他操作系统))
1 unix % swig -python example.i
2
3 unix % gcc -c example.c example_wrap.c
4
5 -I/usr/local/include/python2.1
- 4. 6
7 unix % ld -shared example.o example_wrap.o -o _example.so
我们现在可以使用如下 Python 模块。
1 >>> import example
2
3 >>> example.fact(5)
4
5 120
6
7 >>> example.my_mod(7,3)
8
9 1
10
11 >>> example.get_time()
12
13 'Sun Feb 11 23:01:07 1996'
14
15 >>>
建立 Perl 模块
你可以建立如下的 Perl 模块,如 Solaris 请见 SWIG 共享帮助手册其他操作系统)
1 unix % swig -perl5 example.i
2
3 unix % gcc -c example.c example_wrap.c
4
5 `perl -MExtUtils::Embed -e ccopts`
6
7 unix % ld -G example.o example_wrap.o -o example.so
8
9 unix % perl
10
11 use example;
12
13 print $example::My_variable,quot;nquot;;
14
15 print example::fact(5),quot;nquot;;
- 5. 16
17 print example::get_time(),quot;nquot;;
18
19 <ctrl-d>
20
21 3.0
22
23 120
24
25 Sun Feb 11 23:01:07 1996
26
27 unix %
建立 Java 模块
SWIG 也会产生 JNI 代码以便 Jave 代码进入 C/CC++。以下是建立一个 Jave 模
块的事例(cygwin ,见 swig 维基共享库页帮助其他操作系统)
1 $ swig -java example.i
2
3 $ gcc -c example.c example_wrap.c -I/c/jdk1.3.1/include -I/c/jdk1.3.1/include/win32
4
5 $ gcc -shared example.o example_wrap.o -mno-cygwin -Wl,--add-stdcall-alias -o example.dll
6
7 $ cat main.java
8
9 public class main {
10
11 public static void main(String argv[]) {
12
13 System.loadLibrary(quot;examplequot;);
14
15 System.out.println(example.getMy_variable());
16
17 System.out.println(example.fact(5));
18
19 System.out.println(example.get_time());
20
21 }
- 6. 22
23 }
24
25 $ javac main.java
26
27 $ java main
28
29 3.0
30
31 120
32
33 Mon Mar 4 18:20:31 2002
34
35 $
建立 C# 模块
SWIG 也会产生代码以便 C#使用 Pinvoke 进入 C/CC++。以下是如何建立 C#模块
事例。cygwin ,见 swig 维基共享库页帮助其他操作系统。使用了开源 DotGNU
Portable.NET 能够在大多数 Unix 系统上运行,和其他 C# compilers 一样方便使
用。
1 $ swig -csharp example.i
2
3 $ gcc -c -fpic example.c example_wrap.c
4
5 $ gcc -shared example.o example_wrap.o -o libexample.so
6
7 $ cscc -o runme *.cs
8
9 $ cat runme.cs
10
11 using System;
12
13 public class runme {
14
15 static void Main() {
16
17 Console.WriteLine(example.My_variable);
- 7. 18
19 Console.WriteLine(example.fact(5));
20
21 Console.WriteLine(example.get_time());
22
23 }
24
25 }
26
27 $ ilrun runme
28
29 3
30
31 120
32
33 Tue May 13 10:45:45 2003
34
35 $
SWIG 懒人方法
如上所见,并非总是需要写一个专门的接口文件。如果你有一个头文件,你可以
直接在其中包含 SWIG 接口,如例:
1 %module example
2
3 %{
4
5 /* Includes the header in the wrapper code */
6
7 #include quot;header.hquot;
8
9 %}
10
11
12
13 /* Parse the header file to generate wrappers */
14
15 %include quot;header.hquot;
- 8. 另外,有些人可能只包括 SWIG 条件指令在头文件中。例如:
1 #ifdef SWIG
2
3 %module example
4
5 %{
6
7 #include quot;header.hquot;
8
9 %}
10
11 #endif
12
13
14
15 extern int fact(int n);
16
17
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...
- 9. 上述例子都很简单,但是大体思路已经延伸到复杂的 C/C++。事实上,重
要的是明白 SWIG 一个完整的 C++支持下几乎能包含所有语言的特征。这
些包括预处理,指针,类,甚至 C++模块。SWIG 能够在特定语言打包结
构和类变成 PROXY。
见下列:
为了说明这一点,假设你想要包以下 C++数据结构:
1 // pair.h. A pair like the STL
2
3 namespace std {
4
5 template<class T1, class T2> struct pair {
6
7 T1 first;
8
9 T2 second;
10
11 pair() : first(T1()), second(T2()) { };
12
13 pair(const T1 &f, const T2 &s) : first(f), second(s) { }
14
15 };
16
17 }
为了装载 SWIG 你需要如下接口
1 // pair.i - SWIG interface
2
3 %module pair
4
5 %{
6
7 #include quot;pair.hquot;
8
9 %}
- 10. 10
11
12
13 // Ignore the default constructor
14
15 %ignore std::pair::pair();
16
17
18
19 // Parse the original header file
20
21 %include quot;pair.hquot;
22
23
24
25 // Instantiate some templates
26
27
28
29 %template(pairii) std::pair<int,int>;
30
31 %template(pairdi) std::pair<double,int>;
32
33
现在编译(Python)
1 $ swig -python -c++ pair.i
2
3 $ c++ -c pair_wrap.c -I/usr/local/include/python2.1
4
5 $ c++ -shared pair_wrap.o -o _pair.so
6
7 $ python
8
9 Python 2.1 (#3, Aug 20 2001, 15:41:42)
- 11. 10
11 [GCC 2.95.2 19991024 (release)] on sunos5
12
13 Type quot;copyrightquot;, quot;creditsquot; or quot;licensequot; for more information.
14
15 >>> import pair
16
17 >>> a = pair.pairii(3,4)
18
19 >>> a.first
20
21 3
22
23 >>> a.second
24
25 4
26
27 >>> a.second = 16
28
29 >>> a.second
30
31 16
32
33 >>> b = pair.pairdi(3.5,8)
34
35 >>> b.first
36
37 3.5
38
39 >>> b.second
40
41 8