乐趣区

Python的C/C++扩展——用SWIG封装C++为Python模块

如果觉得文章对你有帮助,你也可以访问老猿的个人博客 https://www.yuanrenxue.com/
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

退出移动版