python中ctypes使用方法

 更新时间:2024年04月24日 11:36:49   作者:平时不搬砖  
这篇文章主要介绍了python中ctypes使用方法,包括 python和c中类型映射,操作结构体和联合体,需要定义结构体或联合体的类型,然后可以创建实例、访问其成员等,感兴趣的朋友跟随小编一起看看吧

前段时间接到了一个需求是给一个蓝牙的SDK测试接口的稳定性,将SDK的接口文档给你了,需要每个接口都写一个对应的测试用例,SDK 是用c写的,而我python用的比较熟练些,所有记录下在ctypes库的使用方法。

1 python和c中类型映射

ctypes中数据类型

ctypes 类型C 类型Python 数据类型
c_bool_Boolbool (1)
c_charchar单字符字节串对象
c_wcharwchar_t单字符字符串
c_bytecharint
c_ubyteunsigned charint
POINTER(c_ubyte)uchar*int
c_shortshortint
c_ushortunsigned shortint
c_intintint
c_uintunsigned intint
c_longlongint
c_ulongunsigned longint
c_longlong__int64 或 long longint
c_ulonglongunsigned __int64 或 unsigned long longint
c_size_tsize_tint
c_ssize_tssize_t 或 Py_ssize_tint
c_floatfloatfloat
c_doubledoublefloat
c_longdoublelong doublefloat
c_char_pchar * (NUL terminated)字节串对象或 None
c_wchar_pwchar_t * (NUL terminated)字符串或 None
c_void_pvoid *int 或 None

2 加载共享库

import ctypes  
# 加载本地的共享库,路径根据实际情况调整  
lib = ctypes.CDLL('./libexample.so')  # Linux/macOS平台  
# lib = ctypes.WinDLL('example.dll')  # Windows平台

3 调用函数

# 设置参数类型  
lib.add.argtypes = [ctypes.c_int, ctypes.c_int]  
# 设置返回类型  
lib.add.restype = ctypes.c_int  
# 调用C函数  
result = lib.add(2, 3)  
print(result)  # 输出:5

4 操作指针

在ctypes中,你可以使用pointer和byref来操作指针。

# 创建一个整数数组  
arr = (ctypes.c_int * 5)(1, 2, 3, 4, 5)  
# 获取指向数组首元素的指针  
ptr = ctypes.pointer(arr)  
# 通过指针访问数组元素  
print(ptr[0])  # 输出:1  
# 使用byref创建指向变量的指针  
x = ctypes.c_int(10)  
px = ctypes.byref(x)  
# 通过指针修改变量的值  
lib.increment(px)  # 假设有一个increment函数用于增加整数的值  
print(x.value)  # 输出:11
# 调用系统的库函数测试
from ctypes import c_int, c_float, create_string_buffer, CDLL, byref
c_lib = CDLL('/lib/x86_64-linux-gnu/libc.so.6')
i = c_int()
f = c_float()
s = create_string_buffer(b"\000" * 32)
print(i.value, f.value, repr(s.value))
# brref 传入数据类型返回指针的地址, create_string_buffer返回的是指针
c_lib.sscanf(b"1 3.14 Hello", b"%d %f %s", byref(i), byref(f), s)
print(i.value, f.value, repr(s.value))
from ctypes import c_int, POINTER, cdll
i = c_int(42)   # 创建一个int类型变量
pi = POINTER(c_int)(i)  # 定义一个指向int类型的指针
print(pi.contents)   # 打印指针指向的内存地址
print(pi.contents.value)   # 打印指针指向的值
# 定义C库中的函数原型
sum_func = cdll.LoadLibrary('./test1.so').sums
sum_func.argtypes = [POINTER(c_int), POINTER(c_int)]    # 定义函数参数类型为指针类型
sum_func.restype = POINTER(c_int)   # 定义函数返回值类型为指针类型
pointer = POINTER(c_int)
# 调用sum()函数
a = c_int(1)
b = c_int(2)
c = sum_func(pointer(a), pointer(b))   # 将a、b的地址传递给sum()函数
print(c.contents.value)   # 打印返回值

5 操作结构体和联合体

你需要定义结构体或联合体的类型,然后可以创建实例、访问其成员等。

# 定义C语言的结构体类型  
class Point(ctypes.Structure):  
    _fields_ = [("x", ctypes.c_int), ("y", ctypes.c_int)]  
# 创建结构体的实例  
p = Point()  
p.x = 10  
p.y = 20  
# 将结构体的实例传递给C函数  
lib.print_point(p)  # 假设有一个print_point函数用于打印点的坐标

6 处理字符串

字符串通常以字符数组或字符指针的形式存在。在ctypes中,你可以使用create_string_buffer来创建C风格的字符串,或者使用c_char_p来操作字符串指针。

# 创建C风格的字符串  
c_str = ctypes.create_string_buffer(b"Hello, World!")  
# 将字符串传递给C函数  
lib.print_string(c_str)  # 假设有一个print_string函数用于打印字符串  
# 处理C语言中的字符串指针  
c_char_p_type = ctypes.POINTER(ctypes.c_char)  
c_char_p = c_char_p_type.from_buffer(c_str)  
lib.print_string_ptr(c_char_p)  # 假设有一个print_string_ptr函数接收字符串指针

7 回调函数

c 中很多实现异步的方式通过回调函数事件触发的方式,ctype中也能将ctype定义的函数传入c中执行

# include "stdio.h"
typedef int (*CallbackFunc)(int, int);
int c_sub(int x, int y){
    printf("c callback func\n");
    return x - y;
}
void call_callback(CallbackFunc callback){
    int result = callback(3, 4);
    printf("result from c: %d\n", result);
}
import ctypes
my_lib = ctypes.CDLL("./test2.so")
callback_type = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int)
def python_sub(a, b):
    print("python callback func")
    return b - a
# 1.调用c中的函数,回调函数从python中传入
python_callback = callback_type(python_sub)
my_lib.call_callback(python_callback)
# 2.调用c中的函数,回调从c中传入
c_callback = callback_type(my_lib.c_sub)
my_lib.call_callback(c_callback)

到此这篇关于python中ctypes使用的文章就介绍到这了,更多相关python ctypes使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python全局变量关键字global的简单使用

    Python全局变量关键字global的简单使用

    python中global关键字主要作用是声明变量的作用域,下面这篇文章主要给大家介绍了关于Python全局变量关键字global的简单使用,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • 使用python查找windows系统中所有程序的安装信息

    使用python查找windows系统中所有程序的安装信息

    这篇文章主要为大家介绍了使用python查找windows系统中所有程序的安装信息示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • python实现简单ftp客户端的方法

    python实现简单ftp客户端的方法

    这篇文章主要介绍了python实现简单ftp客户端的方法,涉及ftplib模块的相关使用技巧,需要的朋友可以参考下
    2015-06-06
  • Python基于随机采样一至性实现拟合椭圆(优化版)

    Python基于随机采样一至性实现拟合椭圆(优化版)

    这篇文章主要对上一版的Python基于随机采样一至性实现拟合椭圆的优化,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的可以了解一下
    2022-11-11
  • Django使用详解:ORM 的反向查找(related_name)

    Django使用详解:ORM 的反向查找(related_name)

    今天小编就为大家分享一篇Django使用详解:ORM 的反向查找(related_name),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-05-05
  • Python学习笔记之读取文件、OS模块、异常处理、with as语法示例

    Python学习笔记之读取文件、OS模块、异常处理、with as语法示例

    这篇文章主要介绍了Python学习笔记之读取文件、OS模块、异常处理、with as语法,结合实例形式简单分析了Python针对文件、目录的读取、异常处理等相关操作技巧,需要的朋友可以参考下
    2019-06-06
  • 深入详解Python解析带有命名空间XML的多种方法

    深入详解Python解析带有命名空间XML的多种方法

    XML命名空间是XML技术中​​不可或缺​​的重要组成部分,它通过提供元素和属性的唯一标识,本文将深入探讨Python中解析带有命名空间的XML文档的各种方法和技术,希望对大家有所帮助
    2025-09-09
  • python实点云分割k-means(sklearn)详解

    python实点云分割k-means(sklearn)详解

    这篇文章主要为大家详细介绍了Python实点云分割k-means,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • Python如何自动生成环境依赖包requirements

    Python如何自动生成环境依赖包requirements

    这篇文章主要介绍了Python如何自动生成环境依赖包requirements问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • 利用python绘制蜂群图的示例代码

    利用python绘制蜂群图的示例代码

    蜂群图可以不重叠的显示各数据点的分布,相对于散点图,所绘制的点彼此靠近且不会重叠,能有效呈现出点分布的局部密度信息,本文给大家介绍了如何利用python绘制蜂群图,文中有详细的代码示例供大家参考,需要的朋友可以参考下
    2024-03-03

最新评论