這段時間一直在摸索swing,用它來封裝C++代碼來生成python腳步語言。並總結了swing從安裝到配置再到代碼封裝編譯生成動態庫的整個過程,下面這篇文章都是我在實際的運用中的一些經驗總結,分享給大家。
Python調用C/C++代碼的利器除了boost_python外,還有SWIG(Simplified Wrapper and Interface Generator),它是用來為腳本語言調用C和C++程序的軟件開發工具,它實際上是一個編譯器,獲取C/C++的聲明和定義,用一個殼封裝起來,以便其它腳本語言訪問這些聲明。所以,SWIG 最大的好處就是將腳本語言的開發效率和 C/C++ 的運行效率有機的結合起來。
前面的文章提到一個C++實現的雙數組Trie Tree的實現:cedar,它在中文分詞、新詞發現等算法中的應用。本文以cedar的SWIG封裝實現來說明SWIG的使用。
0. 安裝swig
工欲善其事必先利其器,首先要安裝swig,Ubuntu安裝swig很簡單:
sudo aptitude install swig
1. 聲明和定義C/C++代碼
在cedar的swig目錄下面有cedar的C++聲明和實現代碼trie.h,但是這個實現里面沒有遍歷所有key的函數方法,所以我添加了一個實現,首先定義一個數據結構來定義key:
// key-value pair return type for next_key() class kv_t { public: std::string key; int value; };
添加一個函數每次返回一個key,當key字符串為空時表示遍歷結束,繼續調用的話就又從頭開始遍歷:
// to iterate all keys kv_t next_key() const { static size_t from = 0, p = 0; union { int i; int x; } b; char key[256] = {0}; kv_t kv; if(from == 0) { b.i = _t->begin(from, p); }else{ b.i = _t->next(from, p); } if (b.i == trie_t::CEDAR_NO_PATH) { kv.key = ""; kv.value = 0; from = 0; p = 0; return kv; } _t->suffix(key, p, from); kv.key = key; kv.value = b.x; return kv; }
2. 編寫接口文件.i
查看cedar.i可以看到SWIG的接口文件的編寫規則:
- 首先在 %module 后面聲明模塊名稱,這就是Python在import時使用的模塊名稱;
- 在%{ … %}之間包含相關頭文件
- 在%include 后面可以聲明對STL的支持
- 最后聲明要封裝的函數和變量,也可以之間包含頭文件: %include “trie.h”
3. 封裝代碼
可以在Makefile里面看到python-bindings:
python-bindings: swig -Wall -python -builtin -outdir python -c++ cedar.i mv -f cedar_wrap.cxx python
直接make或者單獨運行上面的swig命令,就可以生成cedar.py和cedar_wrap.cxx文件。
4. 編譯生成動態庫
編譯生成的cedar_wrap.cxx使用python distutils的setup,可以參考python/setup.py的編寫。setup.py的build如下:
python setup.py build
就會在當前目錄下面創建目錄build,下面生成lib.linux-x86_64-2.7/cedar.py 和 _cedar.so
我的python學習筆記:www.yuanrenxue.com