衆所周知,SWIG這個項目創建的緣由,是爲你們提供簡潔而又天然的腳本語言接口。什麼是簡潔而天然呢?它的意思就是C/C++的函數就直接被封裝爲python的函數,class就被封裝成python的class。 這樣你們用起來就不會變扭。下面講一講一些SWIG所支持的初級的C/C++特性。python
1 函數linux
函數乃是代碼複用之源。SWIG對於函數的封裝之道至簡。封裝完以後在python裏直接做爲模塊的方法調用。數組
%module example int fact(int n);
>>> import example >>> print example.fact(4) 24 >>>
2 全局變量函數
c語言中的各類類型的變量在python中均可以使用。全局變量被放在模塊的cvar這個變量中。this
//file: foo.c #include <stdio.h> int bar = 2; float barfloat = 3.14; double bardouble=3.1415926; short barshort=10000; long barlong=200; long long barlonglong=2000000000000ll; unsigned barunsigned = 200; int barFunc() { printf("this is bar %d.\n" "barfloat %f\n" "bardouble %f\n" "barshort %hd\n" "barlong %ld\n" "barlonglong %lld\n" "barunsigned %u\n" ,bar,barfloat, bardouble,barshort, barlong,barlonglong, barunsigned); return 0; }
//file: foo.i %module foo %{ extern int bar; extern float barfloat; extern double bardouble; extern short barshort; extern long barlong; extern long long barlonglong; extern unsigned barunsigned; %} int bar; float barfloat; double bardouble; short barshort; long barlong; long long barlonglong; unsigned barunsigned; int barFunc();
須要注意的是,全局變量必需在.i文件中extern一下。不然編譯foo_wrap.c的時候會報錯。指針
使用的時候直接使用foo.var.xxx就能夠了。好比code
[GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import foo >>> foo.bar Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'module' object has no attribute 'bar' >>> print foo.cvar.bar 2
特別值得注意的是, 每個類型的數字在python中也會作範圍檢查,若是賦值超過了該類型的範圍,python會拋overflowerror.orm
>>> foo.cvar.barunsigned=-1 Traceback (most recent call last): File "<stdin>", line 1, in <module> OverflowError: in variable 'barunsigned' of type 'unsigned int'
另外,假如修改一個const全局變量,會引起一個segment fault。 因此處理const全局變量的最好方法是使用%immutable 和%mutable。 這兩個關鍵字分別表明只讀和可寫的變量。對象
%immutable; int barconst;
[GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import foo >>> foo.cvar.barconst=2 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: Variable barconst is read-only. >>>
這樣作只會引起異常,而不會引起更致命的段錯誤。 %immutable指令會一直有效,直到你顯示的使用%mutable指令爲止。接口
假如你以爲cvar這個名字不夠酷,你也能夠爲他換一個別的名字。只要在執行swig時候使用-globals varname 參數。
swig -python -globals variable foo.i
3 SWIG的const變量和枚舉變量
除了直接使用C語言模塊中定義的變量,在SWIG腳本中,也能夠爲python腳本定義的const變量和枚舉變量。能夠用到的技術有#define, enum,%constant。 其中enum枚舉變量須要也寫進你的xxx_wrap.c代碼中去。
%{ enum People{Man,Woman}; %} #define PI 3.1415 #define VERSION "1.0" enum People{Man,Woman}; %constant int barconstant=100;
使用這種變量就不須要經過cvar了。由於這就是Python腳本自身定義的變量,和你的C語言的代碼無關。
Type "help", "copyright", "credits" or "license" for more information. >>> import foo >>> foo.VERSION '1.0' >>> foo.PI 3.1415000000000002 >>> foo.Woman 1 >>> foo.Man 0 >>> foo.barconstant 100
4 指針
由於PYTHON裏面並無指針,因此SWIG只是將指針處理成了一種對象。
%module foo FILE* fopen(const char* fname,const char* mode); int fputs(const char*,FILE*); int fclose(FILE*);
咱們能夠直接將庫函數封裝起來使用。
[GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import foo >>> foo.fopen("test","w") <Swig Object of type 'FILE *' at 0xb741c620> >>> f=foo.fopen("test","w") >>> foo.fputs("1234\n",f) 1 >>> foo.fclose(f) 0
5 數組
PYTHON裏沒有數組。所以SWIG只能將數組的首地址做爲一個指針進行一次封裝。也就是說,在PYTHON中,你只能把這個數組當成指針來用。它能夠被傳遞給參數爲指針的函數做爲參數。也能夠被另外一個數組進行賦值,實際上賦值進行的就是內存拷貝,而並不會改變指針的地址。能夠看下面的例子。
//file: ary.c #include <stdio.h> int a[5]={1,2,3,4,5}; int b[6]={10,20,30,40,50,60}; void PrintArray(int *a,size_t n) { size_t i=0; printf("{"); for(i=0;i<n;i++) { printf("%d,",*a++); } printf("}\n"); } void pa() { PrintArray(a,sizeof(a)/sizeof(int)); } void pb() { PrintArray(b,sizeof(b)/sizeof(int)); }
//file: ary.i %module ary %{ extern int a[5]; extern int b[6]; extern void pa(); extern void pb(); %} int a[5]; int b[6]; void pa(); void pb();
#file: testary.py import ary print "a is:" ary.pa() print str(ary.cvar.a) print "b is:" print str(ary.cvar.b) ary.pb() print "\n" ary.cvar.a=ary.cvar.b print "After a=b" print "a is:" ary.pa() print str(ary.cvar.a) print "b is:" print str(ary.cvar.b) ary.pb()
運行結果:
a is: {1,2,3,4,5,} _306720b7_p_int b is: _446720b7_p_int {10,20,30,40,50,60,} After a=b a is: {10,20,30,40,50,} _306720b7_p_int b is: _446720b7_p_int {10,20,30,40,50,60,}
能夠看到,運行a=b並無改變a指針指向的位置,而只是將b數組的前5個元素拷貝到a指針指向的位置而已。
你能夠在此處下載本文中的例子 https://dl.dropbox.com/u/35106490/swig3.tgz