¿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 |
---|---|---|
_Bool |
booleano (1) |
|
carbonizarse |
Objeto de bytes de un solo carácter |
|
|
cadena de un solo carácter |
|
carbonizarse |
En t |
|
carácter sin firmar |
En t |
|
corto |
En t |
|
corto sin firmar |
En t |
|
En t |
En t |
|
entero sin firmar |
En t |
|
largo |
En t |
|
largo sin firmar |
En t |
|
__int64 o largo largo |
En t |
|
sin firmar __int64 或 sin firmar largo largo |
En t |
|
|
En t |
|
|
En t |
|
flotar |
flotar |
|
doble |
flotar |
|
doble largo |
flotar |
|
char* (terminado en NUL) |
objeto de bytes o |
|
wchar_t* (terminado en NUL) |
cuerda o |
|
vacío* |
entero o |
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_callback
que 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_callback
que 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 ~