ctypes使用浅谈

什么是ctypes:

  ctypes 是 Python 的一个标准库,用于与 C 语言进行交互。它提供了一组工具和函数,可以方便地调用动态链接库(DLL)或共享对象(SO)中的 C 函数,并处理 C 数据类型的转换。

说的易懂点就是ctypes在c与python之间做类型转换的。既然是做类型转换的,那么对于c/c++中常用的类型,是如何用ctypes方式去做转换的,接下来一探究竟:

什么是动态链接库:

  动态链接库是一个已经编译好、程序在运行时就可直接使用的数据-函数库。与静态链接库不同,动态链接库在程序运行时被加载和链接,而不是在编译时动态链接库必须先载入,为此ctypes提供三个对象:cdll、windll(windows-only)、oledll(windows-only),并使得载入dll就如访问这些对象的属性一样。这三个区别是:

(1) cdll:cdll对象载入使用标准cdecl调用约定的函数库

(2) windll:windll对象载入使用stdcall调用约定的函数库

(3) oledll:oledll对象载入使用stdcall调用约定的函数库

使用步骤:

(1) 加载动态链接库:

  使用 ctypes 的 cdll 或 windll (Windows 平台)函数来加载动态链接库或共享对象。只需要提供库的路径或名称,ctypes 将自动根据操作系统的不同来选择正确的加载函数,

示例如下:


# 示例 1: 加载动态链接库
my_lib = ctypes.CDLL('/path/to/my_lib.so')
 
# 示例 2: 加载共享对象(在 Windows 上)
my_lib = ctypes.windll.LoadLibrary('my_lib.dll')

(2) 获取DLL/共享库中的函数

my_function = my_lib.my_function # my_function 是动态库中已导出的函数,不导出则不可调用,像访问一个类实例属性一样来载入my_function.argtypes = [ctypes.c_int, ctypes.c_float] my_function.restype = ctypes.c_double # 指定函数的返回类型和参数类型。

(3) 进行类型转换,从而可以传给调用的c函数:  

(1)C语言中基础的数据类型

这部分的使用比较简单,直接使用ctypes内置的方法创建对象即可,ctypes提供的方法和C语言对应的数据类型如下表:

ctypes 类型

C 类型

Python 类型

c_bool

_Bool

bool (1)

c_char

char

单字符字节串对象

c_wchar

wchar_t

单字符字符串

c_byte

char

int

c_ubyte

unsigned char

int

c_short

short

int

c_ushort

unsigned short

int

c_int

int

int

c_uint

unsigned int

int

c_long

long

int

c_ulong

unsigned long

int

c_longlong

__int64 或 long long

int

c_ulonglong

unsigned __int64 或 unsigned long long

int

c_size_t

size_t

int

c_ssize_t

ssize_t 或 Py_ssize_t

int

c_float

float

float

c_double

double

float

c_longdouble

long double

float

c_char_p

char* (以 NUL 结尾)

字节串对象或 None

c_wchar_p

wchar_t* (以 NUL 结尾)

字符串或 None

c_void_p

void*

int 或 None

使用的几个小示例:


import ctypes
 
# 加载动态链接库
my_lib = ctypes.CDLL('/path/to/my_lib.so')
 
# 定义函数原型
my_function = my_lib.my_function
my_function.argtypes = [ctypes.c_int]
 
# 转换整型数据类
my_int = 10
my_function(ctypes.c_int(my_int))
 
#转换浮点型数据类型:
my_float = 3.14
my_function(ctypes.c_float(my_float))
 
#转换字符串类型:
my_string = "Hello"
my_function(ctypes.c_char_p(my_string.encode('utf-8')))#转换数组类型:char_array = c_char * 3

(2)C语言中高级数据类型

对于 C 语言中的高级数据类型,如结构体、嵌套结构体、结构体数组、结构体指针等,ctypes 提供了一些工具和方法来进行转换。假设在 C 代码中有一个结构体类型 MyStruct,下面是几个示例:

import ctypes
 
# 定义 C 结构体类型
class MyStruct(ctypes.Structure):
    _fields_ = [("field1", ctypes.c_int),
                ("field2", ctypes.c_float)]
 
# 加载动态链接库
my_lib = ctypes.CDLL('/path/to/my_lib.so')
 
# 定义函数原型
my_function = my_lib.my_function
my_function.argtypes = [MyStruct]
 
# 创建结构体实例并传递给 C 函数
my_struct = MyStruct()
my_struct.field1 = 10
my_struct.field2 = 3.14
my_function(my_struct)
#转换嵌套结构体
class InnerStruct(ctypes.Structure):
    _fields_ = [("inner_field", ctypes.c_int)] # 定义 C 内部引用结构体class OuterStruct(ctypes.Structure):
    _fields_ = [("outer_field", ctypes.POINTER(InnerStruct))] # 创建结构体实例,并传递给 C 函数
inner = InnerStruct()
inner.inner_field = 10
 
outer = OuterStruct()
outer.outer_field = ctypes.pointer(inner)
 
my_function(ctypes.cast(ctypes.pointer(outer), ctypes.POINTER(OuterStruct)))array_size = 5
my_array = (MyStruct * array_size)()
for i in range(array_size):
    my_array[i].field1 = i
    my_array[i].field2 = float(i)
 
my_function(my_array, array_size)#转换结构体指针和结构体指针数组:#对于结构体指针和结构体指针数组,可以使用 ctypes.POINTER 类型和 ctypes.cast 函数进行转换。# 定义函数原型
my_function = my_lib.my_function
my_function.argtypes = [ctypes.POINTER(MyStruct)]
 
# 创建结构体实例,并传递给 C 函数
my_struct = MyStruct()
my_struct.field1 = 10
my_struct.field2 = 3.14
 
# 传递结构体指针给 C 函数
my_function(ctypes.pointer(my_struct))
 
# 创建结构体指针数组,并传递给 C 函数
array_size = 5
my_array = (ctypes.POINTER(MyStruct) * array_size)()
for i in range(array_size):
    my_array[i] = ctypes.pointer(MyStruct())
     
my_function(ctypes.cast(my_array, ctypes.POINTER(ctypes.POINTER(MyStruct)))) 

(3)C语言中回调函数的转换

假设在 C 代码中有一个函数 register_callback,它接受一个函数指针作为参数,并在适当的时候调用该函数。我们可以使用 ctypes 来定义回调函数,并将其传递给 register_callback

首先,我们需要定义回调函数的类型,然后将其转换为函数指针类型。在调用 register_callback 时,我们将转换后的函数指针作为参数传递。

import ctypes
 
# 定义回调函数类型
CallbackFunc = ctypes.CFUNCTYPE(None, ctypes.c_int)
 
# 定义回调函数
def my_callback(value):
    print("Callback called with value:", value)
 
# 加载动态链接库
my_lib = ctypes.CDLL('/path/to/my_lib.so')
 
# 定义函数原型
register_callback = my_lib.register_callback
register_callback.argtypes = [CallbackFunc]
 
# 将 Python 回调函数转换为函数指针
callback_func = CallbackFunc(my_callback)
 
# 注册回调函数
register_callback(callback_func)

首先使用 ctypes.CFUNCTYPE 定义了回调函数类型 CallbackFunc。它的第一个参数是回调函数的返回类型,这里是 None,表示没有返回值;第二个参数是回调函数的参数类型,这里是 ctypes.c_int

然后,我们定义了 Python 中的回调函数 my_callback,它接受一个整数参数,并在函数内部打印该参数的值。

接下来,我们使用 CallbackFunc 将 Python 回调函数转换为函数指针类型 callback_func

最后,我们加载动态链接库,并调用 register_callback 函数,将转换后的函数指针作为参数传递给 C 函数。


 资料获取方法

【留言777】

各位想获取源码等教程资料的朋友请点赞 + 评论 + 收藏,三连!

三连之后我会在评论区挨个私信发给你们~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/69100.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL中基础查询语句

用户表user数据如下: iddevice_idgenderageuniversityprovince12138male21北京大学Beijing23214male复旦大学Shanghai36543famale20北京大学Deijing42315female 23 浙江大学ZheJiang55432male25山东大学Shandong 1,写出ddl语句创建如上表,…

自动化实践-全量Json对比在技改需求提效实践

1 背景 随着自动化测试左移实践深入,越来越多不同类型的需求开始用自动化测试左移来实践,在实践的过程中也有了新的提效诉求,比如技改类的服务拆分项目或者BC流量拆分的项目,在实践过程中,这类需求会期望不同染色环境…

6.6 实现卷积神经网络LeNet训练并预测手写体数字

模型架构 代码实现 import torch from torch import nn from d2l import torch as d2lnet nn.Sequential(nn.Conv2d(1,6,kernel_size5,padding2),nn.Sigmoid(),#padding2补偿5x5卷积核导致的特征减少。nn.AvgPool2d(kernel_size2,stride2),nn.Conv2d(6,16,kernel_size5),nn.S…

竞赛项目 深度学习实现语义分割算法系统 - 机器视觉

文章目录 1 前言2 概念介绍2.1 什么是图像语义分割 3 条件随机场的深度学习模型3\. 1 多尺度特征融合 4 语义分割开发过程4.1 建立4.2 下载CamVid数据集4.3 加载CamVid图像4.4 加载CamVid像素标签图像 5 PyTorch 实现语义分割5.1 数据集准备5.2 训练基准模型5.3 损失函数5.4 归…

IT运维:使用数据分析平台监控PowerStore存储(进阶)

概述 本文基于《IT运维:使用鸿鹄监控PowerStore存储》(以下简称原文)文章进行了优化。主要优化部分包括存储日志进入到鸿鹄后,如何进行字段抽取,以及图表的展示。 字段抽取:由原来采用视图的方式&#xff0…

干货丨学完网络安全专业,我掌握了哪些技能?

andy Ng在我校完成网络防御与司法大专(Diploma in Network Defense and Forensic Countermeasures)之后,顺利升入我校的网络安全本科课程,目前她就职于一家金融机构并担任安全操作中心的分析专员。在进入我校就读之前,Sandy在建筑行业领域工作…

数学建模—多元线性回归分析(+lasso回归的操作)

第一部分:回归分析的介绍 定义:回归分析是数据分析中最基础也是最重要的分析工具,绝大多数的数据分析问题,都可以使用回归的思想来解决。回归分析的人数就是,通过研究自变量X和因变量Y的相关关系,尝试去解释…

解决遥感技术在生态、能源、大气等领域的碳排放监测及模拟问题

以全球变暖为主要特征的气候变化已成为全球性环境问题,对全球可持续发展带来严峻挑战。2015年多国在《巴黎协定》上明确提出缔约方应尽快实现碳达峰和碳中和目标。2019年第49届 IPCC全会明确增加了基于卫星遥感的排放清单校验方法。随着碳中和目标以及全球碳盘点的现…

2000-2022年全国各地级市绿色金融指数数据

2000-2022年全国各地级市绿色金融指数数据 1、时间:2000-2022年 2、来源:来源:统计局、科技部、中国人民银行等权威机构网站及各种权威统计年鉴,包括全国及各省市统计年鉴、环境状况公报及一些专业统计年鉴,如 《中国…

【深度学习笔记】TensorFlow 基础

在 TensorFlow 2.0 及之后的版本中,默认采用 Eager Execution 的方式,不再使用 1.0 版本的 Session 创建会话。Eager Execution 使用更自然地方式组织代码,无需构建计算图,可以立即进行数学计算,简化了代码调试的过程。…

KAFKA第二课之生产者(面试重点)

生产者学习 1.1 生产者消息发送流程 在消息发送的过程中,涉及到了两个线程——main线程和Sender线程。在main线程中创建了一个双端队列RecordAccumulator。main线程将消息发送给RecordAccumulator,Sender线程不断从RecordAccumulator中拉取消息发送到K…

泰国的区块链和NFT市场调研

泰国的区块链和NFT市场调研 基本介绍 参考: https://zh.wikipedia.org/zh-hans/%E6%B3%B0%E5%9B%BD参考: https://hktdc.infogram.com/thsc–1h7k2303zo75v2x zz制度: 君主立宪制(议会制) 国王: 玛哈哇集拉…

基于vue3+webpack5+qiankun实现微前端

一 主应用改造(又称基座改造) 1 在主应用中安装qiankun(npm i qiankun -S) 2 在src下新建micro-app.js文件,用于存放所有子应用。 const microApps [// 当匹配到activeRule 的时候,请求获取entry资源,渲染到containe…

JVM内存管理

文章目录 1、运行时数据区域1.1 程序计数器(线程私有)1.2 JAVA虚拟机栈(线程私有)1.3 本地方法栈1.4 Java堆(线程共享)1.5 方法区(线程共享)1.6 直接内存(非运行时数据区…

拥抱AIGC浪潮,亚信科技将如何把握时代新增量?

去年底,由ChatGPT带起的AIGC浪潮以迅雷不及掩耳之势席卷全球。 当互联网技术的人口红利逐渐消退之际,AIGC就像打开通用人工智能大门的那把秘钥,加速开启数智化时代的到来。正如OpenAI CEO Sam Altman所言:一个全新的摩尔定律可能…

560. 和为 K 的子数组

思路 本题的主要思路为创建一个哈希表记录每个0~i的和,在遍历这个数组的时候查询有没有sum-k的值在哈希表中,如果有,说明有个位置到当前位置的和为k。   有可能不止一个,哈希表负责记录有几个sum-k,将和记录下来。这…

10个问题,带你重新认识smardaten企业级无代码

很多新客户在接触数睿数据,或者在初步认识smardaten企业级无代码的时候,大家更多地以为只是个普通的无代码工具。在交流过程中,大家也提出了很多疑惑: smardaten无代码平台包括哪些能力? 适合开发哪些应用&#xff1f…

AI自动驾驶

AI自动驾驶 一、自动驾驶的原理二、自动驾驶的分类三、自动驾驶的挑战四、自动驾驶的前景五、关键技术六、自动驾驶的安全问题七、AI数据与自动驾驶八、自动驾驶的AI算法总结 自动驾驶技术是近年来备受关注的热门话题。它代表了人工智能和机器学习在汽车行业的重要应用。本文将…

web集群学习:源码安装nginx配置启动服务脚本、IP、端口、域名的虚拟主机

目录 1、源码安装nginx,并提供服务脚本。 2、配置基于ip地址的虚拟主机 3、配置基于端口的虚拟主机 4、配置基于域名的虚拟主机 1、源码安装nginx,并提供服务脚本。 1、源码安装会有一些软件依赖 (1)检查并安装 Nginx 基础依赖…

PHP智能人才招聘网站mysql数据库web结构apache计算机软件工程网页wamp

一、源码特点 PHP智能人才招聘网站 是一套完善的web设计系统,对理解php编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 下载地址 https://download.csdn.net/download/qq_41221322/88199392 视频演示 PH…