程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> SWIG入門3: C/C++初級特性

SWIG入門3: C/C++初級特性

編輯:C++入門知識

SWIG這個項目建立的原因,是為大家提供簡潔而又自然的腳本語言接口。什麼是簡潔而自然呢?它的意思就是C/C++的函數就直接被封裝為python的函數,class就被封裝成python的class。 這樣大家用起來就不會變扭。下面講一講一些SWIG所支持的初級的C/C++特性。

1 函數

函數乃是代碼復用之源。SWIG對於函數的封裝之道至簡。封裝完之後在python裡直接作為模塊的方法調用。

1 %module example 

2 int fact(int n);


1 >>> import example 

2 >>> print example.fact(4) 

3 24

4 >>>

2 全局變量

c語言中的各種類型的變量在python中都可以使用。全局變量被放在模塊的cvar這個變量中。

01 //file: foo.c 

02 #include <stdio.h> 

03 int bar = 2; 

04 float barfloat = 3.14; 

05 double bardouble=3.1415926; 

06 short barshort=10000; 

07 long  barlong=200; 

08 long long barlonglong=2000000000000ll; 

09 unsigned barunsigned = 200; 

10   

11   

12 int barFunc() 

13 { 

14     printf("this is bar %d.\n"

15             "barfloat %f\n"

16             "bardouble %f\n"

17             "barshort %hd\n"

18             "barlong  %ld\n"

19             "barlonglong %lld\n"

20             "barunsigned %u\n"

21             ,bar,barfloat, 

22             bardouble,barshort, 

23             barlong,barlonglong, 

24             barunsigned); 

25     return 0; 

26 }


01 //file: foo.i 

02 %module foo 

03 %{ 

04 extern int bar; 

05 extern float barfloat; 

06 extern double bardouble; 

07 extern short  barshort; 

08 extern long   barlong; 

09 extern long long barlonglong; 

10 extern unsigned barunsigned; 

11 %} 

12   

13 int bar; 

14 float barfloat; 

15 double bardouble; 

16 short  barshort; 

17 long   barlong; 

18 long long barlonglong; 

19 unsigned barunsigned; 

20 int barFunc();


 需要注意的是,全局變量必需在.i文件中extern一下。否則編譯foo_wrap.c的時候會報錯。

使用的時候直接使用foo.var.xxx就可以了。比如

1 [GCC 4.4.5] on linux2 

2 Type "help", "copyright", "credits" or "license" for more information. 

3 >>> import foo 

4 >>> foo.bar 

5 Traceback (most recent call last): 

6   File "<stdin>", line 1, in <module> 

7 AttributeError: 'module' object has no attribute 'bar'

8 >>> print foo.cvar.bar 

9 2

特別值得注意的是, 每一個類型的數字在python中也會做范圍檢查,如果賦值超過了該類型的范圍,python會拋overflowerror.

1 >>> foo.cvar.barunsigned=-1

2 Traceback (most recent call last): 

3   File "<stdin>", line 1, in <module> 

4 OverflowError: in variable 'barunsigned' of type 'unsigned int'

另外,假如修改一個const全局變量,會引發一個segment fault。 所以處理const全局變量的最好方法是使用%immutable 和%mutable。 這兩個關鍵字分別代表只讀和可寫的變量。

1 %immutable; 

2 int barconst;


1 [GCC 4.4.5] on linux2 

2 Type "help", "copyright", "credits" or "license" for more information. 

3 >>> import foo 

4 >>> foo.cvar.barconst=2

5 Traceback (most recent call last): 

6   File "<stdin>", line 1, in <module> 

7 AttributeError: Variable barconst is read-only. 

8 >>>

這樣做只會引發異常,而不會引發更致命的段錯誤。 %immutable指令會一直有效,直到你顯示的使用%mutable指令為止。

假如你覺得cvar這個名字不夠酷,你也可以為他換一個別的名字。只要在執行swig時候使用-globals varname 參數。

view sourceprint?1 swig -python -globals variable foo.i

3 SWIG的const變量和枚舉變量

除了直接使用C語言模塊中定義的變量,在SWIG腳本中,也可以為python腳本定義的const變量和枚舉變量。可以用到的技術有#define, enum,%constant。 其中enum枚舉變量需要也寫進你的xxx_wrap.c代碼中去。

1 %{ 

2 enum People{Man,Woman}; 

3 %} 

4 #define PI 3.1415 

5 #define VERSION "1.0" 

6   

7 enum People{Man,Woman}; 

8 %constant int barconstant=100;

使用這種變量就不需要通過cvar了。因為這就是Python腳本自身定義的變量,和你的C語言的代碼無關。

01 Type "help", "copyright", "credits" or "license" for more information. 

02 >>> import foo 

03 >>> foo.VERSION 

04 '1.0'

05 >>> foo.PI 

06 3.1415000000000002

07 >>> foo.Woman 

08 1

09 >>> foo.Man 

10 0

11 >>> foo.barconstant 

12 100


4 指針

因為PYTHON裡面並沒有指針,所以SWIG只是將指針處理成了一種對象。

1 %module foo 

2 FILE* fopen(const char* fname,const char* mode); 

3 int fputs(const char*,FILE*); 

4 int fclose(FILE*);

我們可以直接將庫函數封裝起來使用。

01 [GCC 4.4.5] on linux2 

02 Type "help", "copyright", "credits" or "license" for more information. 

03 >>> import foo 

04 >>> foo.fopen("test","w") 

05 <Swig Object of type 'FILE *' at 0xb741c620> 

06 >>> f=foo.fopen("test","w") 

07 >>> foo.fputs("1234\n",f) 

08 1

09 >>> foo.fclose(f) 

10 0

5 數組

PYTHON裡沒有數組。因此SWIG只能將數組的首地址作為一個指針進行一次封裝。也就是說,在PYTHON中,你只能把這個數組當成指針來用。它可以被傳遞給參數為指針的函數作為參數。也可以被另一個數組進行賦值,實際上賦值進行的就是內存拷貝,而並不會改變指針的地址。可以看下面的例子。
01 //file: ary.c 

02 #include <stdio.h> 

03 int a[5]={1,2,3,4,5}; 

04 int b[6]={10,20,30,40,50,60}; 

05   

06 void PrintArray(int *a,size_t n) 

07 { 

08     size_t i=0; 

09     printf("{"); 

10     for(i=0;i<n;i++) 

11     { 

12         printf("%d,",*a++); 

13     } 

14     printf("}\n"); 

15 } 

16   

17 void pa() 

18 { 

19     PrintArray(a,sizeof(a)/sizeof(int)); 

20 } 

21   

22 void pb() 

23 { 

24     PrintArray(b,sizeof(b)/sizeof(int)); 

25 }
01 //file: ary.i 

02 %module ary 

03 %{ 

04   

05 extern int a[5]; 

06 extern int b[6]; 

07   

08 extern void pa(); 

09 extern void pb(); 

10 %} 

11   

12 int a[5]; 

13 int b[6]; 

14 void pa(); 

15 void pb();


01 #file: testary.py 

02 import ary 

03 print "a is:"

04 ary.pa() 

05 print str(ary.cvar.a) 

06 print "b is:"

07 print str(ary.cvar.b) 

08 ary.pb() 

09   

10 print "\n"

11 ary.cvar.a=ary.cvar.b 

12   

13 print "After a=b"

14 print "a is:"

15 ary.pa() 

16 print str(ary.cvar.a) 

17 print "b is:"

18 print str(ary.cvar.b) 

19 ary.pb()

運行結果:

view sourceprint?01 a is: 

02 {1,2,3,4,5,} 

03 _306720b7_p_int 

04 b is: 

05 _446720b7_p_int 

06 {10,20,30,40,50,60,} 

07   

08   

09 After a=b 

10 a is: www.2cto.com

11 {10,20,30,40,50,} 

12 _306720b7_p_int 

13 b is: 

14 _446720b7_p_int 

15 {10,20,30,40,50,60,}

可以看到,運行a=b並沒有改變a指針指向的位置,而只是將b數組的前5個元素拷貝到a指針指向的位置而已。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved