python扩展模块开发
- 在某些情况下,为了追求高性能或绕过python的一些限制(比如GIL全局锁)等,我们可以使用c或c++来为python开发特殊的模块,提升python效率(如cjson,cpickle等库)。
- python 提供了一套非常完整的c api,也有非常丰富的文档,官方文档见:https://docs.python.org/2/c-api/
- 这里主要介绍一些必要实用的c api函数,开发实例和c api以python2.7为准(因为公司用的就是python2.7)
- 如果要看更详细的实例,之后我会在我的一些c/c++文章中加入python的接口实现
准备说明
- Python.h文件: 此文件是python c api的入口文件,所有api都包含在此文件里面
- Py_和_Py: python c api的方法与变量前缀,在代码中尽量不要使用此前缀,避免混乱
- PyObject: python对象,包含引用计数与对象指针,所以的输入输出都通过此对象
- bool: 布尔类型,C是没有bool类型的,python c api的bool类型定义在asdl.h中,形式如下:typedef enum {false, true} bool;,即false=0,true=1
注意事项
- windows环境编译:需要将python27.lib改为python27_d.lib,并且要注意编译的位数,如果编译的是32位,那链接的必须是python32位的库。编译后的lib库,如果要使用,需要将.lib后缀修改为.pyd。另外如果要在其它机器上使用此pyd库,需要注意依赖的lib是否都存在,否则会报“找不到指定的模块”
- 接口描述列表:列表最后一个元素必须是{ 0, 0 , 0, 0 }结尾
- 模块初始化:初始化函数定义格式如下:PyMODINIT_FUNC init{模块名},例如PyMODINIT_FUNC inittest(void)
实用API说明
Py_INCREF函数
函数原型:void Py_INCREF(PyObject *o)
功能说明:增加对象引用计数,会影响对象的GC回收。注意:对象不能为NULL,如果不知道对象是否为空,请使用Py_XINCREF()
返回说明:无返回值
O:要操作的对象
注意:在开发扩展模块时,基本不需要使用到此函数Py_DECREF函数
函数原型:void Py_DECREF(PyObject *o)
功能说明:减少对象引用计数,会影响对象的GC回收。注意:对象不能为NULL,如果不知道对象是否为空,请使用Py_XDECREF()
返回说明:无返回值
O:要操作的对象
注意:在开发扩展模块时,一般情况下,只有对python c对象操作错误的时候,才需要减少对象的引用计数Py_InitModule函数
函数原型:PyObject* Py_InitModule(char *name, PyMethodDef *methods)
功能说明:根据名称和函数表创建一个新的模块对象
返回说明:返回一个新的模块对象
name:模块名称
methods:模块函数描述表
注意:这个函数是扩展模块必须的Py_InitModule3函数
函数原型:PyObject* Py_InitModule3(char *name, PyMethodDef *methods, char *doc)
功能说明:根据名称和函数表创建一个新的模块对象,与Py_InitModule函数功能相似,多一个doc,用于模块描述
返回说明:返回一个新的模块对象
doc:模块描述Py_InitModule函数示例
#include <Python.h>
#ifdef WIN32
// 注意:如果是在windows上开发,需要将python27.lib改为python27_d.lib
// 注意:如果是在windows上开发,32位与64位程序编译需要链接同样位数的python库
#pragma comment(lib,"python27_d.lib")