声明: 本文非原创, 基本转载自这篇文章, 略有修改.
swig (simplified wrapper and interface generator) 可以把c/cpp代码包装成python/ruby等接口. 本文主要记录如何用swig包装c/cpp为python模块的相关资料.
c/cpp 包装为 python 的几种方法:
Python C Api
python解释器提供的一组 c api, 详见官网. 可以用c/cpp实现python module, 也可以将python解释器作为一个脚本引擎嵌入c/cpp代码中, 为c/cpp程序提供解释python脚本的能力. python c api 是其他工具的基础, 可以认为其他工具方法都是基于 python c api 的封装. 官方 python c api 可以理解为底层, 强大的同时意味着比较繁琐, 容易出错, 如果不是相当的高手, 还是较少采用这种方法.
ctypes
ctypes是python标准库提供的调用动态链接库的模块, 使用该模块可以直接在python代码里加载动态链接库, 调用其中的函数. ctypes的优势是使用简单, 不用编写或修改c/cpp代码. 目前还不了解ctypes对c/cpp的支持是否完整.
boost.python
boost提供的cpp的模板库, 用来支持python和cpp的无缝互操作. 相对swig来说, 这个库的优势是功能通过cpp api 完成, 不用学习新的语法 ( swig 就需要再学习swig的用法). boost.python的问题是: 1) 由外部依赖; 2) 文档不友好, tutorial都很难跑通.
swig
swig 完整支持ANSI C, 支持除嵌套类外的所有cpp特性. swig是一个接口编译器, 旨在为c/cpp方便的提供脚本语言接口. google 也使用swig.
swig 概览
swig 接口描述文档
swig本质是个代码生成器, 为c/cpp程序生成到其他语言的包装代码(wrapper code), 这些包装代码里会礼用各语言提供的 c api, 将c/cpp程序中的内容暴露给相应的语言. 为了生成这些代码, swig需要一个接口描述文件, 描述将什么样的接口暴露给其他语言.
swig的接口描述文件可以包含以下内容:
- ANSI C 函数原型声明
- ANSI C 变量声明
- swig 指示器(directive)相关内容
swig可以直接接受.h头文件作为接口描述文件, 在有了接口描述文件后, 就可以礼用swig命令生成包装代码了. 然后将包装代码编译链接成可被其他语言调用的库.
swig可以实现以下功能:
- 用python调用c/cpp库
- 用python继承cpp类, 并在python中使用该继承类
- cpp使用python扩展(通过文档描述应该可以支持, 未验证)
本文中使用swig 1.3.40版本.
swig 官方文档说明
swig官方文档有两大部分, 一部分是其基础文档, 另一部分是针对各语言的文档. 建议直接看具体语言对应的文档, 遇到问题再查找基础文档.
- 基础文档
swig的基本使用, 对c/cpp的支持, swig库及其扩展库
- 各语言文档
例如python, ruby等.
swig 包含内容
swig主要包含以下几部分:
- 代码生成器(swig)
代码生成器根据接口说明文件, 生成对应的包装代码
- 库
swig将常用的内容放到库里, 比如对数组, 指针, 字符串, STL的支持, 可以在接口文件中直接引用库里的内容, 方便接口文件的编写.
- 简单示例
example.h
1 | #include <iostream> |
example.cpp
1 | #include "example.h" |
example.i
1 | %module example |
运行下面的命令:
1 | swig -c\+\+ -python example.i |
如果编译通过的话, 可以在python中测试:
1 | >>> import example |
以上是用distutils构建了 example module, 也可以通过编译器直接构建, 如下:
1 | gcc -fPIC -I/usr/include/python2.5/ -lstdc\+\+ -shared -o _example.os example_wrap.cxx example.cpp |
注意, -fPIC 和 -lstdc++ 都是必需的, _example.os 前面的下划线(‘_‘)也是必需的.