快速实现python c扩展模块

1  python扩展模块的组成

  在python中,对于一些和系统相关的模块或者对性能要求很高的模块,通常会把这个模块C化。扩展模块中主要包含下面几个部分:

  • init函数,函数名为:init+模块名,这个函数负责初始化模块,包括设置模块中的方法、对象和其它相关数据的初始化。这个函数是必须的,在脚本中第一次导入这个模块的时候,会先执行这个方法。
  • 定义模块方法描述表,它是一个static类型的PyMethodDef数据结构,用来描述模块中定义的方法。
  • C函数定义,这些函数是方法描述表中方法的具体实现。
  • 如果模块中定义了类,那么还要定义类方法描述表和对象类型。

2  实现python扩展模块实例

  当然,有了上面的组成部分,你还是不知道怎么实现一个模块,下面就用官方的一个例子来演示怎么实现一个python扩展模块,这个扩展模块用来实现在python中执行命令行命令。

 #include    PyObject *   PyObject *     spam_system(PyObject *self, PyObject *        *            (!PyArg_ParseTuple(args, , &              sts =      (sts <          PyErr_SetString(SpamError,                    PyMethodDef SpamMethods[] =     {          {NULL, NULL, , NULL}                initspam(      PyObject *      m = Py_InitModule(      (m ==               SpamError = PyErr_NewException(      PyModule_AddObject(m,  }

  上面的initspam是模块的初始化函数,函数开始调用了Py_InitModule初始化了一个名为spam的模块,模块的方法描述表是SpamMethods,它描述了模块有个名为system的方法,这个方法的c/c++实现是spam_system函数。从spam_system函数可以看到它就是调用system函数执行从python传过来的命令。有了上面的代码,我们怎样在python中使用了?很简单,先将上面代码编译成动态链接库,然后直接在python中用import语句导入这个模块就可以用了。在Windows下的用vs编译就行,不过在vs建立了dll工程后,需要设置下工程的属性,目的是设置python扩展涉及到的头文件路径和动态库。具体设置如下:先在VC++目录中设置include和lib路径,然后在链接器的附加依赖项中添加python27.lib库。

  设置好后直接编译就可以了,将编译生成的dll文件后缀名改成pyd,然后就可以在python中直接用import导入这个模块了。是不是非常的简单!!!!

3  实现python扩展模块中定义类

  上面的实现是在模块中定义函数来实现执行命令行命令,我们也可以在模块中定义类,然后用类的方法来执行这个命令。代码如下:

 #include    PyObject *   PyObject *     spam_system(PyObject *self, PyObject *        *            (!PyArg_ParseTuple(args, , &              sts =      (sts <          PyErr_SetString(SpamError,                    PyMethodDef SpamMethods[] =     {          {NULL, NULL, , NULL}           PyTypeObject *SpamType =       initspam(       PyTypeObject _SpamType =          ,                                         ,                         (PyObject),                         ,                                         ,                 ,                                         ,                                         ,                                         ,                                         ,                     ,                                         ,                                         ,                                         ,                                         ,                                         ,                     ,                                         ,                                         ,                                         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE ,             ,                             ,                                         ,                                         ,                                         ,                                         ,                                         ,                                         SpamMethods,                             ,                                         ,                         ,                                         ,                                         ,                                         ,                                         ,                                         ,                     ,                                         PyType_GenericNew,                       PyObject *      m = Py_InitModule(      (m ==               (PyType_Ready(&_SpamType) <               SpamType = &      PyModule_AddObject(m, , (PyObject*     SpamError = PyErr_NewException(      PyModule_AddObject(m,  }

  上面的代码与之前的代码只是多了个Spam类的定义,使用的时候通过Spam的实例化对象来调用system函数。

4  Python/C API涉及的引用计数问题

  通过上面的例子,是不是觉得写python的C扩展模块非常的简单呢?其实不然,主要是python中有个引用计数问题,在写扩展模块的时候必须非常小心的处理,否则很有容易导致内存泄露。根据python官方的定义,在Python/C API中,引用计数的行为被归纳为三种:new reference、borrow reference和steal reference,前两种用于描述返回PyObject*类型的函数对返回的这个对象的引用计数的行为;后一种用于将一个PyObject*类型传入函数后,函数对这个对象的引用计数的行为。new referenc表示函数将这个对象引用的所有权转交给函数调用者了,由函数的调用者来管理这个引进的计数,也就是说调用者不用这个引用的时候必须显示的调用 Py_DECREF()或者Py_XDECREF()来释放这个引用,典型的函数是PyObject_、PyNumber_PySequence_和PyMapping_;borrow reference与new reference刚好相反,表示函数的调用者只管用这个引用,不用关心它的引用计数,用完了也不用显示调用Py_DECREF()或者Py_XDECREF()来释放这个引用,典型的函数是PyList_GetItem、PyTuple_GetItem;steal reference表示函数内部只会使用这个引用,不会调用Py_INCREF来增加这个引用的引用计数,相当于“偷了”被调用者的一个引用计数,典型的函数是PyList_SetItem()和PyTuple_SetItem()。因此,在编写C扩展的时,如果遇到某个Python/C API不确定是哪种reference的时候,建议查下官方文档,文档中会明确的说明这个函数是哪类reference(如下图所示),这样能大大减少引用计数的问题。

时间: 2025-02-01 17:00:17

快速实现python c扩展模块的相关文章

程序员带你十天快速入门Python,玩转电脑软件开发(二)

关注今日头条-做全栈攻城狮,学代码也要读书,爱全栈,更爱生活.提供程序员技术及生活指导干货. 如果你真想学习,请评论学过的每篇文章,记录学习的痕迹. 请把所有教程文章中所提及的代码,最少敲写三遍,达到熟悉的效果. 声明:本次教程主要适用于已经习得一门编程语言的程序员.想要学习第二门语言.有梦想,立志做全栈攻城狮的你 如果是小白,也可以学习本教程.不过可能有些困难.如有问题在文章下方进行讨论.或者添加QQ群538742639.群马上就满了,名额不多. 上节课主要讲解了以下内容: 为什么学习Pyth

程序员带你十天快速入门Python,玩转电脑软件开发(三)

声明:本次教程主要适用于已经习得一门编程语言的程序员.想要学习第二门语言.有梦想,立志做全栈攻城狮的你 . 如果是小白,也可以学习本教程.不过可能有些困难.如有问题在文章下方进行讨论.或者添加QQ群538742639.群马上就满了,名额不多. 这是高级程序员快速入门Python语言课程.助你快速学习Python语言.这是第三课. 程序员带你十天快速入门Python,玩转电脑软件开发(一) 程序员带你十天快速入门Python,玩转电脑软件开发(二) 因技术知识连贯性,还没有学习前两课的同学,建议点

程序员带你十天快速入门Python,玩转电脑软件开发(一)

关注今日头条-做全栈攻城狮,学代码也要读书,爱全栈,更爱生活.提供程序员技术及生活指导干货. 如果你真想学习,请评论学过的每篇文章,记录学习的痕迹. 请把所有教程文章中所提及的代码,最少敲写三遍,达到熟悉的效果. 声明:本次教程主要适用于已经习得一门编程语言的程序员.想要学习第二门语言的你.有梦想的你,立志做全栈攻城狮. 如果是小白,也可以学习本教程.不过可能有些困难.如有问题在文章下方进行讨论.或者添加QQ群538742639.群马上就满了,名额不多. 目录: 为什么学习Python? Pyt

如何快速入门Python学习呢?

根据TIOBE最新排名 ,Python已超越C#,与Java,C,C++一起成为全球前4大最流行语言,成为互联网时代最受欢迎的编程语言,越来越多的人选择Python,那么如何快速入门Python学习呢?首先你要了解Python,我们从以下几个方面来说. 学完python前景会咋样 其实我个人是很看好python未来的就业前景的,因为我认识太多的工程师都已经在学python,很多都是月收入大几万的 一项专业调查显示,75%的受访者将Python视为他们的主要开发语言,反之,其他25%受访者则将其视

用C语言实现python的扩展模块

用C语言实现python的扩展模块 示例1: 1 Example.c int add(int a,int b) { return a+b; } int sub(int a,int b) { return a -b; } int mul(int a,int b) { return a*b; } int div1(int a,int b) { if(0 == b) { return b; } return a/b; } 2 wrap.c include //python.h中已经包含了常用的头文件

快速搭建Python开发环境

快速搭建Python开发环境·Python入门学习速成系列<1> 当我们在学习一门新的技术或者新的编程语言时,经常感觉无从下手.学习初期往往不知道事先应该准备什么:或者刚开始准备,在安装问题就栽了一个大跟头:甚至我们准备完成后,开始学习是,才发现事先应该准备安装的软件没有到位等.这样或那样的问题就困扰我们学习之初,花费了大量的时间. 本文主要介绍在Windows和Linux主流操作系统上快速部署Python开发环境. 准备Python开发环境 在准备部署Python开发环境时,往往会选择不同的

快速学会Python(实战)

一:学习感悟 (0)学习语言思想和观念的转变是关键 -- 感触分享 乐于善于接受新鲜事物,对新知识充满渴求的欲望: 多交朋友,你可能会做到一门技术一门语言的大牛,你不可能门门精通,互相学习: 参见技术交流群 和 技术blog和社区,之后自己再钻研官方的API 开启一门新技术的策略:1)从一个感兴趣的点入手(培养兴趣),运行一些小示例:2)1-2天简单的过一下基本的语言(可以不变代码):3)1-2天开始把教程里面的一些小程序,自己手动敲一遍:4)2-3天把此语言的数据类型以及包装类型的(类似STL

用C语音编写python的扩展模块,也就是python调c库

用C语音编写python的扩展模块,也就是python调c库   1.用C语言扩展Python的功能: http://www.ibm.com/developerworks/cn/linux/l-pythc/ 2.用C语言编写Python扩展模块: http://hi.baidu.com/jinmu190/blog/item/c5475846eee39c056a63e5f1.html 3.怎样编写python脚本的C扩展模块 http://blog.csdn.net/dengxu11/articl

快速部署Python应用:Nginx+uWSGI配置详解

快速部署Python应用:Nginx+uWSGI配置详解 相比于PHP,Python应用的部署很麻烦,比较常用的方法有fcgi与wsgi,然而这两种都很让人头痛.文章介绍了Nginx+uwsgi的简便方法,来快速的部署Python应用. AD: 在PHP里,最方便的就是deployment了,只要把php文件丢到支持PHP的路径里面,然后访问那个路径就能使用了:无论给主机添加多少PHP应用,只要把目录改好就没你的事了,完全不用关心php-cgi运行得如何,deployment极为方便. 反观Py