刚好趁ubuntu系统崩溃重装系统的闲暇之际,对之前用python3封装KDL库过程中的一些经验进行一番总结。
常见python封装方式
工作中经常会有在python层调用c/cpp实现的功能的需求,常用的封装方式及工具如下:
SWIG
- 支持 Python 2 and 3
- 配置正确的话,可以全自动完成封装(*.i文件需要自己写)
- 当不是全自动的时候,它大多会重复你的.h文件并给出提示
- 除了Python外,还支持其他语言(Java, Ruby, Lua, 等)
- 输出一个本地文件(这个文件会被编译成.pyd)和一个封装(这个封装是python脚本,调用对应生成的.pyd)
- 绑定(Bindings)的性能不是太好,不支持内部类(inner classes)的封装
- 不支持属性(通过getter/setters访问values)
- 文档很全,很容易学习
- google使用了
- C++支持不太好
Boost::Python
- 支持 Python 2, 3和C++的绑定
- 对于新手来说,学习它的语法有一定难度。但是这些语法很直观
- 大量使用了 C++ templates (可能是好事,也可能是坏事),会很明显地提高编译时间
- 随boost库一起发布,且boost库有用,但很大
- 刚开始编译使用boost.python封装好的C++代码时,出现的各种错误
- 一些语法不易学习,像函数返回值时的规则
- 非常可靠、稳定、经过充分测试的库(boost库里的部件都具有这特性)
- 不支持属性
- 支持文档写得比较差,有些功能文档里甚至都没有写。
编译后的pyd文件有些大,这不利于在手机或者嵌入平台使用 - 配合py++使用,几乎可以全自动封装项目
Py++
- 支持 Python 2, 3 和C++的绑定
- 它调用boost.python自动完成项目绑定,相当于boost.python的高级工具
SIP
- 支持 Python 2, 3 和C++的绑定
- 在PyQt中使用过,其他地方很少见它(原始的orocos KDL也使用SIP封装)
ctypes
- python自带库
- 对纯C代码几乎无缝调用
- 仅支持C语音
- 使用起来繁琐
PyCXX
- 支持 Python 2, 3 和C++的绑定
- 轻量级的封装库,用的人挺多
- 只支持C++
- 目前没有自动绑定工具
参考:http://blog.csdn.net/lainegates/article/details/19565823
ctypes库调用纯C库
前面提到对于纯C写成的库,直接用ctypes调用即可,比如我们之前在python里使用can驱动,以及deepmind最新发布的dm_control也是采用ctypes调用mujoco150。
简单示例:
该示例加载mujoco动态链接库,并调用mj_activate激活。
boost python封装
鉴于个人认为boost python达到了工业级封装的要求,因此当时封装KDL时采用了boost python的方案,下面主要介绍boost python中对cpp中常见代码的处理。
Boost Python封装
函数封装
对于简单函数封装,直接定义即可
|
|
简单类封装
简单的类及结构体封装示例
有多个构造函数的,对应多个init即可
如果不希望暴露任何构造函数
Operator处理
目前Boost Python支持常见符号重载,以KDL中Vector对象为例,以下代码实现+、-重载操作
成员变量
以Frame类中M和p为例
类继承
以KDL::ChainIkSolverPos为例,我们知道其继承自KDL::SolverI,封装该类时
虚函数
以KDL::ChainFkSolverPos为例,JntToCart为其纯虚函数
对于带实现的虚函数,以KDL::ChainFkSolverPos_recursive中的JntToCart为例:
默认参数处理
如果C++中函数有默认参数,必须特殊处理,以下简单示例:
封装过程,必须对应不同参数省略形式:
枚举类型处理
对于枚举类型,以JointType为例:
注:之前将KDL::Joint::None直接封装为None使用过程会报错,不太清楚其机制和原理,因此改为NoJoint。
数据切片处理
对于KDL::Vector中三个变量,我们希望封装之后在python层可以像List或者numpy数组一样方便的使用切片[]操作来访问和操作,以操作为例,构造操作函数:
封装时将操作函数封装为setitem即可
Py++实现自动化封装
使用中需要安装gccxml和pygccxml,使用pygccxml自动生成封装cpp文件
注:我当时的代码已经丢失,该脚本仅供理解(实际使用需要修改)。
一般来说Py++生成的封装cpp手动代替了很多工作,对于简单封装也可以直接使用,部分情况会需要人手动继续修改生成的cpp文件。
总结
前面简单总结了在使用Boost Python封装KDL过程中的一些经验,仅供参考。
封装的PyKDL位于 https://github.com/foolyc/PyKDL ,如果在python3环境中有需要,欢迎下载使用。