当前位置:编程学习 > C/C++ >>

SWIG入门3: 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 {&nb

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,