python使用ctypes调用扩展模块的实例方法


Posted in Python onJanuary 28, 2020

楔子

我们知道python的执行效率不是很高,而且由于GIL的原因,导致python不能充分利用多核CPU。一般的解决方式是使用多进程,但是多进程开销比较大,而且进程之间的通信也会比较麻烦。因此在解决效率问题上,我们会把那些比较耗时的模块使用C或者C++编写,然后编译成动态链接库,Windows上面是dll,linux上面则是so,编译好之后,交给python去调用。而且通过扩展模块的方式还可以解决python的GIL的问题,因此如果想要利用多核,我们仍然可以通过扩展模块的方式。

python如何调用扩展模块

python调用扩展模块的一种比较简单的方式就是使用ctypes这个库,这个库是python官方提供的,任何一个版本的python都可以使用,我们通过ctypes可以很轻松地调用扩展模块。

演示

#include <stdio.h>

void test()
{
  printf("hello world\n");
}

我们定义了一个很简单的函数,下面我们就可以将其编译成扩展模块了。在Windows是dll,linux上是so,编译的命令是一样的。我这里以Windows 为例,记得在Windows上要安装MinGW,或者安装VsCode,我这里使用的是MinGW,因为VsCode太大了。

gcc -o dll文件或者so文件 -shared c或者c++源文件

我这里的C源文件叫做1.c,我们编译成mmp.dll吧,所以命令就可以这么写:gcc -o mmp.dll -shared 1.c

python使用ctypes调用扩展模块的实例方法

下面就可以使用python去调用了。

import ctypes

# 使用ctypes很简单,直接import进来,然后使用ctypes.CDLL这个类来加载动态模块
# 如果在Windows上还可以使用ctypes.WinDLL。
# 因为看ctypes源码的话,会发现WinDLL也是一个类并且继承自CDLL
# 所以在linux上使用ctypes.CDLL,
# 而在Windows上既可以使用WinDLL、也可以使用CDLL加载动态模块
lib = ctypes.CDLL("./mmp.dll") # 加载之后就得到了扩展模块
# 我们可以直接通过.的方式去调用里面的函数了,会发现成功打印
lib.test() # hello world

# 但是为了确定是否存在这个函数,我们一般会使用反射去获取
# 因为如果函数不存在通过.的方式调用会抛异常的
func = getattr(lib, "test", None)
if func:
  print(func) # <_FuncPtr object at 0x0000029F75F315F0>
  func() # hello world


# 不存在test_xx这个函数,所以得到的结果为None
func1 = getattr(lib, "test_xx", None)
print(func1) # None

所以使用ctypes去调用扩展模块非常方便

1.通过ctypes.CDLL("dll或者so的路径"),如果是Windows还可以使用ctypes.WinDLL("dll路径")。另外这两种加载方式分别等价于:ctypes.CDLL("dll或者so的路径") == ctypes.cdll.LoadLibrary("dll或者so的路径"),ctypes.WinDLL("dll路径") == ctypes.windll.LoadLibrary("dll路径")。但是注意的是:linux上只能使用ctypes.CDLL和ctypes.cdll.LoadLibrary,而Windows上ctypes.CDLL、ctypes.cdll.LoadLibrary、ctypes.WinDLL、ctypes.windll.LoadLibrary都可以使用。但是一般我们都使用ctypes.CDLL即可,另外注意的是:dll或者so文件的路径最好是绝对路径,即便不是也要表明层级,比如我们这里的py文件和dll文件是在同一个目录下,但是我们加载的时候不可以写mmp.dll,这样会报错找不到,要写成./mmp.dll。

2.加载动态模块之后会返回一个对象,我们上面起名为lib,这个lib就是得到的扩展模块了。

3.然后可以直接通过lib调用里面的函数,但是一般我们会使用反射的方式来获取,因为不知道函数到底存不存在,如果不存在直接调用会抛出异常,如果存在这个函数我们才会执行。

以上就是本次介绍的全部相关知识点,如果大家有任何补充的地方可以联系三水点靠木小编。

Python 相关文章推荐
python中的列表推导浅析
Apr 26 Python
python使用matplotlib绘制柱状图教程
Feb 08 Python
python中MethodType方法介绍与使用示例
Aug 03 Python
Python实现七彩蟒蛇绘制实例代码
Jan 16 Python
Python视频爬虫实现下载头条视频功能示例
May 07 Python
python hashlib加密实现代码
Oct 17 Python
Python时间差中seconds和total_seconds的区别详解
Dec 26 Python
Python生成词云的实现代码
Jan 14 Python
Python 一行代码能实现丧心病狂的功能
Jan 18 Python
记一次pyinstaller打包pygame项目为exe的过程(带图片)
Mar 02 Python
python根据完整路径获得盘名/路径名/文件名/文件扩展名的方法
Apr 22 Python
基于PyQT实现区分左键双击和单击
May 19 Python
Python 时间戳之获取整点凌晨时间戳的操作方法
Jan 28 #Python
使用Python制作新型冠状病毒实时疫情图
Jan 28 #Python
代码总结Python2 和 Python3 字符串的区别
Jan 28 #Python
使用Python爬虫库BeautifulSoup遍历文档树并对标签进行操作详解
Jan 25 #Python
Python爬虫库BeautifulSoup获取对象(标签)名,属性,内容,注释
Jan 25 #Python
Python爬虫库BeautifulSoup的介绍与简单使用实例
Jan 25 #Python
使用Python爬虫库requests发送表单数据和JSON数据
Jan 25 #Python
You might like
常用的php ADODB使用方法集锦
2008/03/25 PHP
php array_intersect()函数使用代码
2009/01/14 PHP
微信公众平台开发实现2048游戏的方法
2015/04/15 PHP
微信公众平台开发(五) 天气预报功能开发
2016/12/03 PHP
php处理静态页面:页面设置缓存时间实例
2017/06/22 PHP
js操作CheckBoxList实现全选/反选(在客服端完成)
2013/02/02 Javascript
IE、FF浏览器下修改标签透明度
2014/01/28 Javascript
js简单的点击返回顶部效果实现方法
2015/04/10 Javascript
JS选项卡动态替换banner图片路径的方法
2015/05/11 Javascript
基于Jquery+div+css实现弹出登录窗口(代码超简单)
2015/10/27 Javascript
JavaScript实现相册弹窗功能(zepto.js)
2016/06/21 Javascript
jQuery实现的无限级下拉菜单功能示例
2016/09/12 Javascript
JavaScript中常用的验证reg
2016/10/13 Javascript
微信小程序 教程之模块化
2016/10/17 Javascript
Vue.js实现无限加载与分页功能开发
2016/11/03 Javascript
JS实现页面进入和返回定位到具体位置
2016/12/08 Javascript
Vue移动端项目实现使用手机预览调试操作
2020/07/18 Javascript
[01:01:24]DOTA2上海特级锦标赛A组败者赛 EHOME VS CDEC第三局
2016/02/25 DOTA
[01:17:47]TNC vs VGJ.S 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
仅利用30行Python代码来展示X算法
2015/04/01 Python
Python实现图像几何变换
2015/07/06 Python
Python使用django搭建web开发环境
2017/06/09 Python
Python线性方程组求解运算示例
2018/01/17 Python
python模块之paramiko实例代码
2018/01/31 Python
Python Logging 日志记录入门学习
2018/06/02 Python
python实现人人自动回复、抢沙发功能
2018/06/08 Python
django解决跨域请求的问题详解
2019/01/20 Python
Python实现动态给类和对象添加属性和方法操作示例
2020/02/29 Python
Python语言编写智力问答小游戏功能
2020/10/13 Python
世界知名接发和假发品牌:Poze Hair
2017/03/08 全球购物
Java如何支持I18N?
2016/10/31 面试题
医药工作者的求职信范文
2013/09/21 职场文书
幼师专业毕业生自荐信
2013/09/29 职场文书
MySQL数据迁移相关总结
2021/04/29 MySQL
SQL Server数据库查询出现阻塞之性能调优
2022/04/10 SQL Server
在MySQL中你成功的避开了所有索引
2022/04/20 MySQL