Python: C扩展初体验
前言
使用 Python 毋庸置疑减少了很多规则约束和开发成本,让我们能够更加专注于逻辑而非语法。但是得此失彼,开发效率提高了,却带来了运行性能的问题,所以就常常被其他门派追着暴打。
身为一个 pythoner,我们也很忧伤呀,怪我们咯..
万幸的是,虽然上帝关掉了我们一扇门,但是却为我们打开了另一扇窗,正因为底层是用 C语言 写的,所以我们可以将一些性能损耗比较大的功能,或者模块,通过 C语言 重写,然后 import xxxx 来无缝结合。
哪怕工作中比较少机会自己写C扩展, 了解这块的知识,也有利于我们更加深入了解 Python 的运行本质。
网上比较是通过 ctypes 或者 setup.py 的方式实现引用和编译安装,这边想试下最原始的方法~
快速开车
1. 实现接口函数
接口函数是什么意思?可以简单理解成就是 Python 和 C 的对接函数,举个栗子:
我们可以看到这个函数和传统意义上的 C 用法用点不同了,特别是在函数形参那边的PyObject self, PyObject args
第一个参数是 PyObject *self,这个参数是Python内部使用的,可以不用管;
第二个参数是 PyObject *args,这个参数非常重要,因为这个揽括了所有传给函数的参数。它是一个参数列表,把所有的参数都整合到
一个 string, 因此,如果我们需要解析这些参数需要用特定的姿势!我们需要用到 PyArg_ParseTuple 来解开这个扣人心弦的入口!
PyArg_ParseTuple 函数说明:
1.args就是需要转换的参数;
2.ii 就是参数类型的格式符号,这里代表 int init;(更多类型请看官网:https://docs.python.org/2/c-a...)
3.后面的 &arg1, &arg2 就是通过参数解析提取的值,存放的地方,这有点类似 C 的 scanf;
很明显,这三个参数,在数量上存在这一定的联系,也就是,传进去两个 int参数,那么就肯定是对应了两个 ii,然后就会对应存在 两个实际的"容器"内,这里要注意,一不小心就会 Segmentation fault
对应有解析参数的,肯定也有 C模块 值转换成 Python对象 的,那就是 Py_BuildValue。
Py_BuildValue 函数说明:
1.第一个参数 和 PyArg_ParseTuple 的第二个参数一样,都是格式化符号;
2.第二个参数是需要转换的参数,函数 Py_BuildValue 会把所有的返回指都组装成 tuple 给 Python
相关的官方文档:https://docs.python.org/2/c-api/arg.html
2. 定义方法列表
PyMethodDef 是一个 C结构体,用来完成一个映射,也就是便于方法查找,我们把需要被外面调用的方法都记录在这表内。
PyMethodDef 结构体成员说明:
1.第一个字段:在 Python 里面使用的方法名;
2.第二个字段:C 模块内的函数名;
3.第三个字段:方法参数类型,是无参数(METH_NOARGS) , 还是有位置参数(METH_VARARGS), 还是其他等等;
4.第四个字段:方法描述,就是通过 help() 或者 doc 可以看到的;
需要注意的是,这个列表的最后必须以 {NULL, NULL, 0, NULL} 的形式来代表声明结束,也有一些大佬用 {NULL, NULL},不过个人觉得写完整也不会累到哪去, 相反会比较直观。
正因为存在这样的一份记录表,Python 才能够寻找到相应的函数
同样的,如果我们想要找一个模块的 Python 函数 对应什么的 C模块方法,也能通过这地方比较粗暴得知,例如 Python 的 list
3. 实现初始化函数 (关键)
需要特别注意的是,这个函数名不能像上面那样,这是有规定的,必须是 init + 模块名字,比方说,我的最后编译出来的文件是 test.so, 那我的函数名就是 inittest, 这样在 Python 导入 test 模块时,才能找到这个函数并调用。
这里调用了 Py_InitModule 函数来将模块名字和映射表结合在一起。表示 test 这个模块使用 testMethods 这个映射表。
4. 注意对象引用管理和内存泄露
Python 在对象管理、内存管理上面,有引用计数,标记-清除,分代回收等策略,其中引用计数发生的频率会非常非常高,依赖这个通常已经能够解决大部分的对象残留问题了。
所以,在我们编写 C扩展 时,也需要时刻谨记这步.
主要会用到下面两个宏:
1. 增加引用: Py_INCREF 例: Py_INCREF(pObj1)
2. 减少引用: Py_DECREF 例: Py_DECREF(pObj1)
不能直接使用 free/delete 释放,必须使用 Py_DECREF(pObj1), 然后 pObj1 = NULL 即可。
具体可以参考:
官网:https://docs.python.org/2/extending/extending.html#reference-counts
垃圾回收机制: http://www.wklken.me/posts/2015/09/29/python-source-gc.html
编译导出
/ -fpic --shared -o test.so test.c
完整例子
test.c
test.py
import test print test.test(1, 2) # 输出 21
感谢作者:Lin_R
转载自https://segmentfault.com/a/1190000015724170
Python: C扩展初体验的更多相关文章
- python窗体——pyqt初体验
连续两周留作业要写ftp的作业,从第一周就想实现一个窗体版本的,但是时间实在太短,qt零基础选手表示压力很大,幸好又延长了一周时间,所以也就有了今天这篇文章...只是为了介绍一些速成的方法,还有初学者 ...
- Python操作RabbitMQ初体验(一)
由于想用Python实现一套分布式系统,来管理和监控CDN的内容与运行状态,误打误撞认识了RabbitMQ,推荐的人很多,如余锋<我为什么要选择RabbitMQ>等等. 在MQ这个词汇映入 ...
- Python函数之初体验
定义函数 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回. 我们先定义一个求字符串长度的函数 ...
- 菜鸟学IT之python词云初体验
作业来源:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2822 1. 下载一长篇中文小说. 2. 从文件读取待分析文本. txt = ...
- Python+Django(Python Web项目初体验)
参考:https://blog.csdn.net/qq_34081993/article/details/79229784 Django是一个开放源代码的Web应用框架,由Python写成. 安装Dj ...
- 简说Python之图形初体验
针对孩子,最容易引起小孩的感官认知的就是图形.因此,系统运用图形编程,可以更好地让孩子喜欢上编程. turtle叫做,Turtle graphics.是python第三方的画图模块工具.可以通过imp ...
- 菜鸟学python之程序初体验
作业来源:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2684 1.字符串操作: 解析身份证号:生日.性别.出生地等. def id ...
- Python导出Excel为Lua/Json/Xml实例教程(二):xlrd初体验
Python导出Excel为Lua/Json/Xml实例教程(二):xlrd初体验 相关链接: Python导出Excel为Lua/Json/Xml实例教程(一):初识Python Python导出E ...
- ipython及Python初体验
阅读目录: Python环境体验 Python编辑器 ipython安装 Python提示符 Python初体验 print和变量 变量操作 内建函数:方法 数学运算:简单算术.随机数 关于模块 一. ...
随机推荐
- Linux学习---Linux用户审计简单版
[root@localhost root]# vim /etc/profile # SHENJI history USER=`whoami` USER_IP=`who -u am i 2>/de ...
- 铁乐学python_Day42_线程池
铁乐学python_Day42_线程池 concurrent.futures 异步调用模块 concurrent.futures模块提供了高度封装的异步调用接口 ThreadPoolExecutor: ...
- 铁乐学python_day09_作业
练习题 1.整理函数相关知识点,写博客 2.写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素, 并将其作为新列表返回给调用者. def odd_index(l): lis = [] for ...
- Cloudstack
1.cloudstack介绍 一个开源具有高可用性及扩展性的云计算平台,Cloudstack是一个开源的云操作系统: cloudstack支持管理大部分主流的hypervisors,如:VMware, ...
- scrapy爬虫框架之Xpath选择器
问题: 本篇博文主要记录scrapy框架爬取伯乐在线文章的相关知识,在实践中学习对框架的理解.今天主要记录了xpath的相关用法以及语法规范. ----->>>点击进入爬取页面 一. ...
- mysql workbench的PK,NN,UQ,BIN,UN,ZF,AI
mysql workbench建表时PK.NN.UQ.BIN.UN.ZF.AI的意思,后面几个老搞不清,随记在这便于以后方便查. [intrinsic column flags] (基本字段类型标识) ...
- ethers.js-2-wallets and signers
Application Programming Interface (API) Wallets and Signers A Wallet manages a private/public key pa ...
- Python Flask高级编程
第1章 课程导语介绍课程的内容1-1 开宗明义 试看1-2 课程维护与提问 第2章 Flask的基本原理与核心知识本章我们首先介绍Python官方推荐的最佳包与虚拟环境管理工具:Pipenv.接着我们 ...
- 使用JS获取上一页的url地址
一般来说每个页面上面都有一个返回按钮,用来返回上一页,代码如下: <a href="javascript:history.go(-1)" class="jsBack ...
- Ext4文件系统架构分析(二)
接着上一篇博文,继续分析Ext4磁盘布局中的元数据. 1.7 超级块 超级块记录整个文件系统的大量信息,如数据块个数.inode个数.支持的特性.管理信息,等待. 如果设置sparse_super特性 ...