通过实例简介python使用ctypes模块调用C语言动态库
看介绍python语言时,说它是胶水语言,可以调用其他语言。通过使用ctypes模块就可以调用C语言的动态库。下面先放上官方文档和几个比较好的博文。
1、官方文档:http://python.net/crew/theller/ctypes/tutorial.html
2、Python调用windows下DLL详解 - ctypes库的使用:
http://blog.csdn.net/magictong/article/details/3075478
3、聊聊Python ctypes 模块:
https://zhuanlan.zhihu.com/p/20152309
4、Python的学习(三十二)---- ctypes库的使用整理
http://blog.csdn.net/linda1000/article/details/12623527
5、ctypes使用指南:
http://blog.csdn.net/samdy2008/article/details/52139142
因为这个实例,自己也只是简单使用没有整明白,所以先把参考的几个文章列出来。
把C语言编译为动态链接库。Windows下动态链接库的扩展名是dll,Linux下是so,Mac OS X下是dylib。
Gcc编译出的动态库,python调用时,可以直接调用原型,不需要做特殊处理。
VS使用的编译器是 MSVC,和g++编译出来的动态库,需要特珠声明才能被调用。因为编译出的函数名实际上不是本来的名字,这也是C++可以重载的原因,真实的函数名已经变了。
头文件中定义
#ifdef __cplusplus
extern "C" { //这个是必须有的
#endif
/*************************************
*函数功能:打开摄像头
不是函数接口,所以不需要特殊处理
*************************************/
INT8U BSP_CameraOpen(INT8U ucPort);
/*************************************
*函数功能:获取图像
因是接口,需要特殊处理
*************************************/
_declspec(dllexport) INT8U BSP_CameraGetPhoto(INT8U ucFormat,INT8U *pDataBuf,INT16U *pDataLen);
/*
拍照片初始化,即创建串口,打开摄像头,之后就可以直接操作读照片了。
因是接口,需要特殊处理
*/
_declspec(dllexport) int ComCamInit(void);
#ifdef __cplusplus
};
#endif
如不特殊处理,python加载库时不会报错,但是调用函数接口时,会抛出找不到函数的异常。(编译库时,函数名字变了嘛)
>>> import ctypes #导入ctypes库
>>> testdll = ctypes.CDLL(r"D:\project program\photo\VS_dll\photo_dll\photo_dll.dll") >>> ret = testdll.ComCamInit() #调用库中的ComCamInit()函数,返回0说明返回成功了。
>>> ret
0
库里的BSP_CameraGetPhoto()函数,参数为INT8U *pDataBuf,INT16U *pDataLen,需要传入一个数组的指针,用于返回获取到的图片数据,和一个short类型的指针用于保存返回的长度。
所以要用到数组的映射和指针的映射,也就是C语言的数据类型转换为ctypes中的数据类型。
基本类型映射
>>>type_uchar_array_20k = ctypes.c_char * (20*1024) #创建一个20K的char型数组类型type_uchar_array_20k
>>> my_array = type_uchar_array_20k() #实例化生成这个20K的char型数组的对象
>>> uwlen = 0 #定义uwlen
>>> uwLenPara= ctypes.c_ushort(uwlen) #这里可以不使用uwlen,而使用0,这里是要告诉 uwLenPara 的类型和值
>>> ret = testdll.BSP_CameraGetPhoto(1,my_array,ctypes.byref(uwLenPara))
>>> ret
40459264
>>> help(ctypes.byref)
Help on built-in function byref in module _ctypes:
byref(...)
byref(C instance[, offset=0]) -> byref-object
Return a pointer lookalike to a C instance, only usable
as function argument
Byref关键字会这个这个对像的指针。
返回结果为40459264( 0x2695C00)
Python中返回的类型默认为int,而库里这个函数返回的类型是unsigned char所以需要指定返回类型,这里最低字节0x00说明返回成功了。
如果动态链接库中的C函数返回值不是int,需要在调用函数之前显式的告诉ctypes返回值的类型
testdll.BSP_CameraGetPhoto.restype = ctypes.c_ubyte
>>> ret = testdll.BSP_RearCommClose() #调用动态库关闭串口句柄
>>> my_array #数组对象
<__main__.c_char_Array_20480 object at 0x02695CB0>
>>> my_array.value #输出数组的值需要用循环,这里只显示四个字节(默认按int显示)
'\xff\xd8\xff\xdb'
>>> uwlen #说明返回值和uwlen 没关系,定义uwLenPara时只是使用了uwlen做为初始值
0
>>> uwLenPara #返回他的类型,和值 6592
c_short(6592)
>>> uwLenPara.value
6592
>>> type_uchar_array_20k #数组类型(比较my_array返回)
<class '__main__.c_char_Array_20480'>
>>> ctypes.byref(uwLenPara) #返回一个指针(02695C88)
<cparam 'P' (02695C88)>
#把获取到的图片数据写到二进制文件里,
>>> with open(r"D:\test123.jpg",'wb') as f:
for i in xrange(uwLenPara.value):
f.write(my_array[i])
实验结果:


通过实例简介python使用ctypes模块调用C语言动态库的更多相关文章
- (转载)Python 的 JPype 模块调用 Jar 包
Python 的 JPype 模块调用 Jar 包 背景与需求 最近学习并安装使用了HttpRunner框架去尝试做接口测试,并有后续在公司推广的打算. HttpRunner由Python开发,调用接 ...
- 关于C#调用非托管动态库方式的性能疑问
最近的项目中,因为一些原因,需要C#调用非托管(这里为C++)的动态库.网上喜闻乐见的方式是采用静态(DllImport)方式进行调用.偶然在园子里看到可以用动态(LoadLibrary,GetPro ...
- C#调用C/C++动态库 封送结构体,结构体数组
一. 结构体的传递 #define JNAAPI extern "C" __declspec(dllexport) // C方式导出函数 typedef struct { int ...
- Android NDK开发及调用标准linux动态库.so文件
源:Android NDK开发及调用标准linux动态库.so文件 预备知识及环境搭建 1.NDK(native development Kit)原生开发工具包,用来快速开发C.C++动态库,并能自动 ...
- linux c编程调用系统的动态库时,要使用dlopen等函数吗?
同问 linux c编程调用系统的动态库时,要使用dlopen等函数吗? 2012-11-27 21:55 提问者: hnwlxyzhl 我来帮他解答 满意回答 2012-12-07 09:08 li ...
- C#调用C/C++动态库,封装各种复杂结构体
C#调用C/C++动态库,封装各种复杂结构体. 标签: c++结构内存typedefc# 2014-07-05 12:10 6571人阅读 评论(1) 收藏 举报 分类: C(8) C#(6) ...
- cpp调用c的动态库
目录 cpp调用c的动态库 title: cpp调用c的动态库 date: 2019/11/22 20:34:29 toc: true --- cpp调用c的动态库 CPP文件里这么引用头文件即可 e ...
- Python多层目录模块调用
一. 引用模块在 父+级目录中: 1. 将导入模块所在目录(../model/模块)添加到系统环境变量path下,可添加多个 import syssys.path.append("../mo ...
- python常见函数以及模块调用
1.常用函数区别 print: 在python3.0中print是函数,这意味着需要编写print(A )而不是print A str()和repr()的区别 >>>print st ...
随机推荐
- [转] Linux多线程编程之pthread
转载出处:https://blog.csdn.net/skyroben/article/details/72793409 1.背景知识 Linux没有真正意义上的线程,它的实现是由进程来模拟,所以属于 ...
- 【知识】定时器setTimeout/setInterval执行时this指针指向问题
[问题描述] setTimetout/setInterval中this指针指向window,以下是一个小demo: var demoChange = { key: true, changeFun() ...
- java大文件上传
上次遇到这样一个问题,客户上传高清视频(1G以上)的时候上传失败. 一开始以为是session过期或者文件大小受系统限制,导致的错误.查看了系统的配置文件没有看到文件大小限制,web.xml中sees ...
- ppt制作的相关技巧
一.好的ppt需要达到的目标是: 用情感打动你,用逻辑说服你 二.好主题,写在封面上 主标题带来冲击力,副标题提供描述性细节 如何打造好标题: (1)用数字给标题添彩 (2)想畅销书学标题 (3)向流 ...
- 大数据笔记(二十七)——Spark Core简介及安装配置
1.Spark Core: 类似MapReduce 核心:RDD 2.Spark SQL: 类似Hive,支持SQL 3.Spark Streaming:类似Storm =============== ...
- 利用IKVM在C#中调Java程序(总结+案例)
IKVM.NET是一个针对Mono和微软.net框架的java实现,其设计目的是在.NET平台上运行java程序.本文将比较详细的介绍这个工具的原理.使用入门(如何java应用转换为.NET应用.), ...
- SVN重命名后,不允许提交
在vs中对文件名重命名后,导致不能提交 解决: 在源码根目录下提交源码,提交完毕后,再使用如下菜单对需要命名的单个文件进行重命名,重命名完毕后,在源码根目录下提交源码即可
- class 用法 函数变量的作用域
函数变量的作用域 1. 函数体内声明的变量 2. 参数中的变量 没有赋值的 function fn(a){} 赋值的,值不是变量 function fn(a=45){} 赋的值为变量 function ...
- learning webrtc 使用node.js
第二章 有使用node.js创建静态服务器的步骤 不过不够详细 下面以Windows为例 1.到官方网站下载安装包 然后安装 2.用管理员权限启动命令行 3.命令行窗口执行npm config set ...
- 我们建了一个 Golang 硬核技术交流群(内含视频福利)
目录 目录 Golang 是什么? 我们为什么选择 Golang? Golang 是云时代的宠儿! 我们搞了一场 Golang 入门直播 Golang 是什么? Golang 是谷歌 2009 年发布 ...