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中将阿拉伯数字转换成中文的实现代码
May 19 Python
Python比较文件夹比另一同名文件夹多出的文件并复制出来的方法
Mar 05 Python
使用Python的Flask框架实现视频的流媒体传输
Mar 31 Python
如何使用七牛Python SDK写一个同步脚本及使用教程
Aug 23 Python
基于Python函数的作用域规则和闭包(详解)
Nov 29 Python
python 解决动态的定义变量名,并给其赋值的方法(大数据处理)
Nov 10 Python
python批量识别图片指定区域文字内容
Apr 30 Python
Python如何爬取微信公众号文章和评论(基于 Fiddler 抓包分析)
Jun 28 Python
解决django后台管理界面添加中文内容乱码问题
Nov 15 Python
Jupyter notebook 启动闪退问题的解决
Apr 13 Python
基于Python实现全自动下载抖音视频
Nov 06 Python
关于django python manage.py startapp 应用名出错异常原因解析
Dec 15 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中的foreach问题
2013/06/30 PHP
19个超实用的PHP代码片段
2014/03/14 PHP
php使用gettimeofday函数返回当前时间并存放在关联数组里
2015/03/19 PHP
PHP aes (ecb)解密后乱码问题
2015/06/22 PHP
php读取torrent种子文件内容的方法(测试可用)
2016/05/03 PHP
PHP 与 UTF-8 的最佳实践详细介绍
2017/01/04 PHP
php实现文件与16进制相互转换的方法示例
2017/02/16 PHP
php str_replace替换指定次数的方法详解
2017/05/05 PHP
关于php unset对json_encode的影响详解
2018/11/14 PHP
YII2框架中ActiveDataProvider与GridView的配合使用操作示例
2020/03/18 PHP
读jQuery之一(对象的组成)
2011/06/11 Javascript
javascript改变position值实现菜单滚动至顶部后固定
2013/01/18 Javascript
一个简单的jquery的多选下拉框(自写)
2014/05/05 Javascript
js 设置缓存及获取设置的缓存
2014/05/08 Javascript
JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模式)
2014/08/16 Javascript
jQuery实现移动 和 渐变特效的点击事件
2015/02/26 Javascript
jQuery插件Zclip实现完美兼容个浏览器点击复制内容到剪贴板
2015/04/30 Javascript
JS阻止事件冒泡行为和闭包的方法
2016/06/16 Javascript
ES6新特性之字符串的扩展实例分析
2017/04/01 Javascript
使用vue实现简单键盘的示例(支持移动端和pc端)
2017/12/25 Javascript
node实现的爬虫功能示例
2018/05/04 Javascript
精读《Vue3.0 Function API》
2020/05/20 Javascript
Element Steps步骤条的使用方法
2020/07/26 Javascript
windows下python模拟鼠标点击和键盘输示例
2014/02/28 Python
使用Python解析JSON数据的基本方法
2015/10/15 Python
python中copy()与deepcopy()的区别小结
2018/08/03 Python
python使用pdfminer解析pdf文件的方法示例
2018/12/20 Python
python圣诞树编写实例详解
2020/02/13 Python
Jupyter notebook如何修改平台字体
2020/05/13 Python
详解CSS3的box-shadow属性制作边框阴影效果的方法
2016/05/10 HTML / CSS
使用CSS3实现字体颜色渐变的实现
2020/08/10 HTML / CSS
CAT鞋美国官网:CAT Footwear
2017/11/27 全球购物
中国京东和泰国中央集团合资的网站:JD CENTRAL
2020/08/22 全球购物
综合素质的自我鉴定
2013/10/07 职场文书
专题组织生活会发言材料
2014/10/17 职场文书
2014年网络管理员工作总结
2014/12/01 职场文书