SWIG入門4: C/C++初級特性2

1 structurepython

我看來,structure乃是封裝之源。SWIG對於strucure的封裝很是天然。天然的意思就是,C語言裏怎麼用PYTHON就怎麼用。水裏水裏來,火裏火裏去。不過第一個問題就是,PYTHON做爲面向對象的語言, 它自己就是沒有struct的。不過不要緊,咱們還有class。c++

使用的方法很是簡單。直接把struct的定義寫到SWIG腳本文件裏面去就行了。數組

struct Vector {
	double x,y,z;
};

使用起來也很是的方便。ide

>>> v = example.Vector()
>>> v.x = 3.5
>>> v.y = 7.2
>>> print v.x, v.y, v.z
7.8 -4.5 0.0
>>>

若是你打印出v的值,你會發現這個實例只是對底層Vector結構體指針的封裝。這個實例自己什麼也不作,它只是一個代理類。能夠用.this的方式訪問Vector結構體的指針。函數

>>> print v
<C Vector instance at _18e31408_p_Vector>
>>> print v.this
_18e31408_p_Vector
>>>

像全局變量同樣,你能夠在結構體定義內部用%immutable和%mutable指令來告訴SWIG哪些字段不可被修改,那些能夠被修改。這兩條指令的做用範圍是在結構體以內的。this

struct Foo {
   ...
   %immutable;
   int x;        /* Read-only members */
   char *name;
   %mutable;
   ...
};

若是你在struct中擁有char* 這種類型的字段,SWIG會用malloc或者new來分配內存呢。具體用哪種要看你在運行swig時候是否使用了-c++這個參數。假如在python中對char*字段從新賦值,會先釋放掉內存再申請一塊新的內存。若是你以爲這種行爲不符合你的要求,你能夠用typemap來自定義行爲。不過之後纔會介紹typemap這個特性。翻譯

若是有數組類型的字段,那麼在python中同樣是看成指針來處理的。好比有這樣的結構體代理

struct Bar {
    int  x[16];
};

python中運行結果以下:指針

>>> b = example.Bar()
>>> print b.x
_801861a4_p_int
>>>

像全局變量同樣,你也能夠用另一個數組給這個數組來賦值,其實是執行的值拷貝操做。code

>>> c = example.Bar()
>>> c.x = b.x             # Copy contents of b.x to c.x

對數組賦值時, python實際上拷貝了b.x的16個int型整數到c.x所指向的位置。不過要注意一點,PYTHON不會爲你作邊界檢查,若是你傳了一個錯誤的地址是頗有可能致使段錯的。

結構體自己能夠做爲其餘結構體的字段。但在swig中,這種結構體類型的字段是做爲指針來處理的。假若有結構體Foo和Bar:

struct Foo {
   int a;
};

struct Bar {
   Foo f;
};

PYTHON中在Bar中能夠像訪問一個普通的屬性同樣訪問Foo結構體。一切都很是天然。

>>> b = Bar()
>>> x = b.f

在這個例子中,x其實只是一個指向Foo的指針。結構體類型的字段和結構體指針類型的字段在SWIG中的處理方式是同樣的。將上面的代碼翻譯成C語言的代碼,就像這樣

Bar b;
Foo *x = &b->f;       /* Points inside b */

 

2 class

c++的class固然也會裝到PYTHON的class的類中。好比下面這個類:

class List {
public:
  List();
  ~List();
  int  search(char *item);
  void insert(char *item);
  void remove(char *item);
  char *get(int n);
  int  length;
};

在PYTHON裏面這樣方便的使用它:

>>> l = example.List()
>>> l.insert("Ale")
>>> l.insert("Stout")
>>> l.insert("Lager")
>>> l.get(1)
'Stout'
>>> print l.length
3
>>>

類的數據成員的訪問方式和struct中基本同樣。除了靜態成員。

靜態成員和PYTHON的訪問方式有些不大相同。SWIG提供兩種訪問類的類成員函數的方法。第一種是直接經過對象來訪問,第二種是能夠經過‘類名_函數名’ 做爲global函數的使用的方式。

>>> example.Spam_foo()    # Spam::foo()
>>> s = example.Spam()
>>> s.foo()               # Spam::foo() via an instance

類數據成員如何訪問,還記得全局變量是怎麼訪問的嗎?  SWIG將全局變量放在一個cvar的模塊對象中。類數據成員的訪問方法也是相似的,也是做爲模塊的全局變量來訪問。

>>> print example.cvar.Spam_bar
7

3 繼承

SWIG徹底支持C++的繼承方式。假若有這樣的類的繼承關係

class Foo {
...
};

class Bar : public Foo {
...
};

你就能夠驚奇的發如今python裏也能夠擁有相同的繼承關係:

>>> b = Bar()
>>> instance(b,Foo)
1
>>> issubclass(Bar,Foo)
1
>>> issubclass(Foo,Bar)
0

 你能夠在此處下載本文中的例子, https://dl.dropbox.com/u/35106490/swig4.tgz

相關文章
相關標籤/搜索