在C语言中,字符串处理是天天都要面对的问题。咱们都知道C语言中其实并无一种原生的字符串类型,‘字符串’在C语言里只是一种特殊的以'\0'结尾的字符数组。所以,如何将C语言与更高层次的Python语言在‘字符串’处理这个问题上对接是一个有难度的问题。所幸有swig这种强大的工具。python
假若有这样一个C语言的函数,linux
<!-- lang: cpp --> void FillZero(char* pc,size_t * piLen) { size_t i=0; while(i++<*piLen/2 ) *pc++ = '0'; *pc = 0; *piLen = i+1; }
这个函数的功能是把字符串变成n个0。不过咱们更关注函数的形式。这样的函数,表面上看char* pc是函数的参数,但是实际上它才是函数的返回值和执行的结果。piLen这个参数既是pc的最大长度,也是新的字符串的长度。咱们直接用python封装,看看运行结果。c++
<!-- lang: python --> Type "help", "copyright", "credits" or "license" for more information. >>> import cchar >>> s='123456' >>> cchar.FillZero(s,6) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: in method 'FillZero', argument 2 of type 'size_t *'
结果差强人意,不是咱们想要获得的结果。函数的第二个参数为size_t* 咱们很难用python来表示,并且python中也不存在既是输入,也是输出的参数。数组
swig有一个标准库,其中有一个cstring.i文件就是用来解决C语言字符串类型的问题。函数
咱们在.i文件中加入这样几行工具
<!-- lang: cpp --> %include "cstring.i" %cstring_output_withsize(char* pc,size_t* pi) void FillZero(char* pc, size_t* pi);
而后运行看结果spa
<!-- lang: python --> Type "help", "copyright", "credits" or "license" for more information. >>> import cchar >>> cchar.FillZero(10) '00000\x00' >>> s=cchar.FillZero(10) >>> print s 00000
咱们看函数的变化。首先在python里, FillZero变成了只有一个参数的函数。而后函数的返回值变成了一个字符串。其实cstring_output_size实际上是一个宏,经过这个宏的定义改变了函数的形式,直接在Python中获得咱们想要的结果。指针
其实相似cstring_output_size的宏还有好几个,我列举一下:code
cstring_output_allocate(char **s,free(*$1)); 第一个参数是指向字符串地址的指针,第二个参数为释放空间的方法。 你们考虑这一下这样的函数:orm
<!-- lang: cpp -->
void foo(char* & s) { s = (char*)malloc(10); memcpy(s,"123456789",9); }
s这个参数表面上看是输入,其实是函数真正的输出。 函数中真正改变的东西是char*&s指向的字符串的值。并且char*&这个类型, python或者其余脚本语言里应该都没有对应的类型。那么咱们用cstring_output_allocate将这个函数转换成另一个形式的python或者其余脚本语言的函数。转换后的函数实际上是这样的,以python为例str foo()。
<!-- lang: cpp --> %module a %include "cstring.i" %{ void foo(char*& s); %} %cstring_output_allocate(char *&s, free(*$1)); void foo(char *&s); 在python中的调用: <!-- lang: python --> >>> import a >>> a.foo() '123456789' >>>
cstring_output_maxsize(char *path, int maxpath); 第一个参数也是能够改变的字符串首地址,第二个参数为字符串的最大长度。在Python中调用的时候,只有maxpath这个参数,返回字符串。
cstring_output_allocate(char **s, free(*$1)); 第一个参数为指向字符串首地址的指针,第二个参数为释放指针的方法。这个宏主要是封装一种直接在函数内部malloc空间的函数。在Python中调用时没有参数,直接返回字符串。
cstring_output_allocate_size(char **s, int slen, free($1)); 这个至关于前面两个函数的组合。在函数内部malloc空间,而后将字符串长度经过slen返回。其实在调用的时候很是简单,没有参数,直接返回字符串。
std::string是C++标准类库STL中常见的类。在平时工做中你们确定是没少用。在python中如何封装std::string? swig提供了标准库
例如函数:
<!-- lang: cpp --> string Repeat(const string& s) { return s+s; }
只要在swig中加入这样几行:
<!-- lang: cpp --> %include "std_string.i" using namespace std; string Repeat(const string& s);
运行结果:
<!-- lang: python --> Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import cchar >>> cchar.Repeat('123') '123123'
使用起来很方便,但须要注意的是,假如函数的参数的内容是能够被修改,就不能用这种方式封装。 例如:
<!-- lang: cpp --> void repeat(string s) { s+=s; }
这样的函数直接使用 'std_string.i' 就是无效的。遇到这种函数,只能用C语言封装成 void repeat(chars, int maxsize), 再用swig调用 'cstring_output_withsize' 这个宏再封装一次了。
本文代码能够今后下载: https://dl.dropbox.com/u/35106490/swig7.tgz