这两天接到一个任务,要求将一个C库封装成python模块,供python使用。以前玩过一阵子python,也没太深入,满足需求就够了。也一直好奇想看看C/C++如何扩展python。
由C/C++写的python模块最终生成为一个.so(Linux平台)文件。在当前目录下就可以import进来了。那先写个简单的模块。
每个模块需要一个初始化函数,函数声明为:
void init模块名();
其中使用Py_InitModule来初始化模块。该函数的第二个参数传递了要导出的函数。定义在了exampleMethods当中。
在exampleMethods当中只导出了一个函数,就是wrap_test。参数类型为METH_VARARGS。意思是将函数参数作为Tuple传递过来。还有其他几种传递方式,可以查阅文档。
python提供了方便的函数用来解析参数PyArg_ParseTuple,使用了类似printf的可变参数。类似的函数还有Py_BuildValue是将c数据类型转换成Python对象。具体python数据类型有具体的函数可以进行转换,也不必要非用Py_BuildValue。
以上就是最简单的一个例子了。导出个简单的函数。
在做python扩展的时候,最值得注意的是对象引用计数。Python中的对象都是通过引用计数实现垃圾收集。在写python扩展要非常小心。否则会造成段错误之类的错误。
首先引用分为两种,一种是新引用(New reference),一种是借用引用(Borrowed reference),就是python当中的弱引用。
python api中的函数返回大多为新引用,部分(PyDict_GetItem)为借用引用。在编写扩展的时候要小心。函数的参数都为借用引用。
使用以下函数增减引用计数:
Py_INCREF
Py_XINCREF
Py_DECREF
Py_XDECREF
Py_CLEAR
就记录这么多了,知道大概这么些个规则,其实就可以开工了,剩下的边写边查文档就可以搞定了。当然用python不用面向对象多么没意思,回头再记录一下用C/C++扩展Python Object。