SWIG入门6: Python Proxy Class和Builtin Type

在前几篇文章中,从一个较高的层次上说明了SWIG的基本用法。这篇文章会深入到SWIG的一些实现的细节中。SWIG默认的封装方式,是把C/C++的struct和class封装到Python Proxy Class中。不过从SWIG 2.0.4开始, swig提供了一个新的参数-builtin, 这种封装的方式比Python Proxy Class更高效。

Python Proxy Class

Python Proxy Class是SWIG封装的一个很关键的部分。Python Proxy Class提供了一个很自然的访问C/C++代码的方式,从而能提供很多SWIG的特性。假如你有这样一段C++的代码:

class Foo {
public:
     int x;
     int spam(int);
     ...

SWIG会把这个类的成员变量和成员函数,封装成一些简单的函数。例如在foo_wrap.cxx中会有一个_wrap_new_Foo这个函数是对于new Foo的封装。在这个函数中,先会动态分配一个Foo对象,然后将这个对象包裹在SwigPyObject对象内,最后将这个SwigPyObject的对象返回。

/*
Foo *new_Foo() {
    return new Foo();
}
*/

SWIGINTERN PyObject *_wrap_new_Foo(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
  PyObject *resultobj = 0; 
  Foo *result = 0 ;
  
  if (!PyArg_ParseTuple(args,(char *)":new_Foo")) SWIG_fail;
  result = (Foo *)new Foo();
  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Foo, SWIG_POINTER_NEW |  0 ); 
  return resultobj;
fail:
  return NULL;
}

在生成的python接口中,在python proxy class Foo 内部其实就是调用wrap_new_foo这个函数来生成一个新的SwigPyObject对象,并且把原生的Foo对象的指针包裹在自己的内部:

class Foo(_object):

    def __init__(self): 
        this = _foo.new_Foo()
        try: self.this.append(this)
        except: self.this = this

 Builtin type

 从Python Proxy Class的细节中,我们可以知道,一个Python对象调用原生的C++对象,实际上是3层封装:

1 Python对象包含SwigPyObject

2 SwigPyObject包含原生的C++的Foo对象

3 原生的C++的Foo对象

层次越多效率越低,为此在swig 2.0.4之后推出了一个Buitin type的特性。利用这个特性实现的Python类,可以越过SwigPyObject这一层,直接包含原生的C++的Foo对象。通过减少封装的层次,提高代码的执行效率。

我们可以采用swig -builtin这个参数来激活这个特性。

通过swig -builtin参数生成的 wrap源代码中有这样的定义:

SWIGINTERN PyMethodDef SwigPyBuiltin__Foo_methods[] = {
  { "bar", (PyCFunction) _wrap_Foo_bar, METH_VARARGS, (char*) "" },
  { NULL, NULL, 0, NULL } /* Sentinel */
};

static PyHeapTypeObject SwigPyBuiltin__Foo_type = {
/*
省略成员的定义
*/
}

定义了一种新的python builtin类型 Foo_type,在python中,可以直接调用Foo_type来操纵Foo*。

不过使用Builtin 特性有一些要注意的点:

1 python 2.3之前的版本不支持

2 不能直接调用函数接口,比如new_foo这样的函数,而是直接调用Foo()

3 对象的静态成员不需要用 .cvar.成员 , 而是直接用 类名.成员

本文的代码可通过下面的链接下载:

https://dl.dropbox.com/u/35106490/swig6.tgz

 

    原文作者:python入门
    原文地址: https://my.oschina.net/u/247956/blog/77464
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞