用CC++扩展Python

    技术2025-09-16  75

       这两天接到一个任务,要求将一个C库封装成python模块,供python使用。以前玩过一阵子python,也没太深入,满足需求就够了。也一直好奇想看看C/C++如何扩展python。

     

      由C/C++写的python模块最终生成为一个.so(Linux平台)文件。在当前目录下就可以import进来了。那先写个简单的模块。

     

      #include <Python.h> int test(int n) { return n + 1; } PyObject *wrap_test(PyObject *self, PyObject *args) { int n = 0; if (!PyArg_ParseTuple(args, "i:fact", &n)) { return NULL; } int ret = Py_BuildValue("i", test(n)); return ret; } static PyMethodDef exampleMethods[] = { {"test", wrap_test, METH_VARARGS, "just test"}, {NULL} }; PyMODINIT_FUNC initexample() { Py_InitModule("example", exampleMethods); } 

     

       每个模块需要一个初始化函数,函数声明为:

       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。

     

    最新回复(0)