Una breve discusión sobre el uso de ctypes.

¿Qué son los tipos?

  ctypes Es una biblioteca estándar de Python para interactuar con el lenguaje C. Proporciona un conjunto de herramientas y funciones que pueden llamar fácilmente funciones C en bibliotecas de vínculos dinámicos (DLL) u objetos compartidos (SO) y manejar la conversión de tipos de datos C.

En pocas palabras, ctypes realiza conversión de tipos entre c y python. Dado que se realiza la conversión de tipos, a continuación descubriremos cómo usar ctypes para convertir los tipos comúnmente utilizados en c/c++:

¿Qué es una biblioteca de enlaces dinámicos?

  La biblioteca de enlaces dinámicos es una biblioteca de funciones de datos que se ha compilado y se puede usar directamente cuando el programa se está ejecutando. A diferencia de las bibliotecas de vínculos estáticos, las bibliotecas de vínculos dinámicos se cargan y vinculan cuando el programa se está ejecutando, en lugar de durante la compilación. La biblioteca de vínculos dinámicos debe cargarse primero. Para este propósito, ctypes proporciona tres objetos: cdll, windll (solo Windows). , oledll (solo para Windows) y hace que cargar el dll sea como acceder a las propiedades de estos objetos. Las tres diferencias son:

(1) cdll: el objeto cdll carga una biblioteca de funciones utilizando la convención de llamada cdecl estándar.

(2) windll: el objeto windll carga una biblioteca de funciones utilizando la convención de llamada stdcall.

(3) oledll: el objeto oledll carga una biblioteca de funciones utilizando la convención de llamada stdcall.

Pasos de uso:

(1) Cargue la biblioteca de enlaces dinámicos:

  Utilice  ctypes la  función cdll o  windll (plataforma Windows) para cargar bibliotecas de vínculos dinámicos u objetos compartidos. Solo necesita proporcionar la ruta o el nombre de la biblioteca y ctypes se seleccionará automáticamente la función de carga correcta según el sistema operativo.

Los ejemplos son los siguientes:


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

(2) Obtener funciones en DLL/biblioteca compartida

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

(3) Realice la conversión de tipo para que pueda pasarse a la función c que llama:  

(1) Tipos de datos básicos en lenguaje C

El uso de esta parte es relativamente simple. Puede utilizar directamente los métodos integrados de ctypes para crear objetos. Los métodos proporcionados por ctypes y los tipos de datos correspondientes al lenguaje C son los siguientes:

tipo de tipos

tipo C

Tipos de Python

c_bool

_Bool

booleano (1)

c_char

carbonizarse

Objeto de bytes de un solo carácter

c_wchar

wchar_t

cadena de un solo carácter

c_byte

carbonizarse

En t

c_ubite

carácter sin firmar

En t

c_corto

corto

En t

c_ushort

corto sin firmar

En t

c_int

En t

En t

c_uint

entero sin firmar

En t

c_long

largo

En t

c_olong

largo sin firmar

En t

c_longlong

__int64 o largo largo

En t

c_ulonglong

sin firmar __int64 或 sin firmar largo largo

En t

c_tamaño_t

size_t

En t

c_ssize_t

ssize_t o  Py_ssize_t

En t

c_flotador

flotar

flotar

c_doble

doble

flotar

c_longdoble

doble largo

flotar

c_char_p

char* (terminado en NUL)

objeto de bytes o None

c_wchar_p

wchar_t* (terminado en NUL)

cuerda o None

c_void_p

vacío*

entero o None

Algunos pequeños ejemplos de uso:


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) Tipos de datos avanzados en lenguaje C

Para tipos de datos avanzados en lenguaje C, como estructuras, estructuras anidadas, matrices de estructuras, punteros de estructuras, etc., ctypes se proporcionan algunas herramientas y métodos para la conversión. Suponga que tiene un tipo de estructura en código C.  MyStruct,A continuación se muestran algunos ejemplos:

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) Conversión de funciones de devolución de llamada en lenguaje C

Suponga que tiene una función en código C  register_callbackque acepta un puntero de función como parámetro y llama a esa función en el momento apropiado. Podemos  ctypes definir una función de devolución de llamada usando y pasársela a  register_callback.

Primero, necesitamos definir el tipo de función de devolución de llamada y luego convertirla en un tipo de puntero de función. Al llamar  register_callback , pasamos el puntero de función convertido como argumento.

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)

Primero use  ctypes.CFUNCTYPE el tipo de función de devolución de llamada definida  CallbackFunc. Su primer parámetro es el tipo de retorno de la función de devolución de llamada, aquí está  None, lo que significa que no hay valor de retorno; el segundo parámetro es el tipo de parámetro de la función de devolución de llamada, aquí está  ctypes.c_int.

Luego definimos una función de devolución de llamada en Python  my_callbackque acepta un argumento entero e imprime el valor de ese argumento dentro de la función.

A continuación,  CallbackFunc convertimos la función de devolución de llamada de Python a un tipo de puntero de función  usando callback_func.

Finalmente, cargamos la biblioteca de enlaces dinámicos y llamamos  register_callback a la función, pasando el puntero de la función convertida como parámetro a la función C.


 Cómo obtener información

【Mensaje 777】

Amigos que quieran obtener el código fuente y otros materiales tutoriales, por favor den Me gusta + comentario + recopilación , ¡tres veces seguidas!

Después de tres rondas consecutivas , les enviaré mensajes privados uno por uno en el área de comentarios ~

Supongo que te gusta

Origin blog.csdn.net/GDYY3721/article/details/132210265
Recomendado
Clasificación