Une brève discussion sur l'utilisation des ctypes

Qu'est-ce que les ctypes :

  ctypes Il s'agit d'une bibliothèque standard de Python pour interagir avec le langage C. Il fournit un ensemble d'outils et de fonctions qui peuvent facilement appeler des fonctions C dans des bibliothèques de liens dynamiques (DLL) ou des objets partagés (SO) et gérer la conversion des types de données C.

Pour faire simple, ctypes effectue la conversion de type entre c et python. Puisque la conversion de type est effectuée, comment utiliser les ctypes pour convertir les types couramment utilisés en c/c++, découvrons ensuite :

Qu'est-ce qu'une bibliothèque de liens dynamiques :

  La bibliothèque de liens dynamiques est une bibliothèque de fonctions de données qui a été compilée et peut être utilisée directement lorsque le programme est en cours d'exécution. À la différence des bibliothèques de liens statiques, les bibliothèques de liens dynamiques sont chargées et liées lors de l'exécution du programme, plutôt que lors de la compilation. La bibliothèque de liens dynamiques doit être chargée en premier. À cette fin, ctypes fournit trois objets : cdll, windll (Windows uniquement). , olell (Windows uniquement) et permet de charger la DLL comme si vous accédiez aux propriétés de ces objets. Les trois différences sont :

(1) cdll : l'objet cdll charge une bibliothèque de fonctions en utilisant la convention d'appel standard cdecl.

(2) windll : l'objet windll charge une bibliothèque de fonctions en utilisant la convention d'appel stdcall.

(3) olell : l'objet oledll charge une bibliothèque de fonctions en utilisant la convention d'appel stdcall.

Étapes d'utilisation :

(1) Chargez la bibliothèque de liens dynamiques :

  Utilisez  ctypes la  fonction cdll ou  windll (plateforme Windows) pour charger des bibliothèques de liens dynamiques ou des objets partagés. Il vous suffit de fournir le chemin ou le nom de la bibliothèque, et ctypes la fonction de chargement correcte sera automatiquement sélectionnée en fonction du système d'exploitation.

Les exemples sont les suivants :


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

(2) Obtenir les fonctions dans la DLL/bibliothèque partagée

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

(3) Effectuez une conversion de type afin qu'il puisse être transmis à la fonction c appelante :  

(1) Types de données de base en langage C

L'utilisation de cette partie est relativement simple. Vous pouvez utiliser directement les méthodes intégrées des ctypes pour créer des objets. Les méthodes fournies par les ctypes et les types de données correspondant au langage C sont les suivants :

type de type

Type C

Types Python

c_bool

_Bool

bouffon (1)

c_char

carboniser

Objet octets à caractère unique

c_wchar

wchar_t

chaîne de caractères unique

c_octet

carboniser

int

c_ubyte

caractère non signé

int

c_short

court

int

c_ushort

court métrage non signé

int

c_int

int

int

c_uint

entier non signé

int

c_long

long

int

c_olong

non signé depuis longtemps

int

c_longlong

__int64 ou long long

int

c_ulonglong

non signé __int64 et non signé long long

int

c_size_t

size_t

int

c_ssize_t

ssize_t ou  Py_ssize_t

int

c_float

flotter

flotter

c_double

double

flotter

c_longdouble

longue double

flotter

c_char_p

char* (terminé par NUL)

objet octets ou None

c_wchar_p

wchar_t* (terminé par NUL)

chaîne ou None

c_void_p

vide*

entier ou None

Quelques petits exemples d'utilisation :


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) Types de données avancés en langage C

Pour les types de données avancés en langage C, tels que les structures, les structures imbriquées, les tableaux de structures, les pointeurs de structure, etc., ctypes certains outils et méthodes sont fournis pour la conversion. Supposons que vous ayez un type struct en code C.  MyStruct,Voici quelques exemples :

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) Conversion des fonctions de rappel en langage C

Supposons que vous ayez une fonction en code C  register_callbackqui accepte un pointeur de fonction comme paramètre et appelle cette fonction au moment approprié. Nous pouvons  ctypes définir la fonction de rappel en utilisant et la transmettre à  register_callback.

Tout d’abord, nous devons définir le type de la fonction de rappel, puis la convertir en un type de pointeur de fonction. Lors de l’appel de  register_callback , nous passons le pointeur de fonction converti en argument.

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)

Utilisez d'abord  ctypes.CFUNCTYPE le type de fonction de rappel défini  CallbackFunc. Son premier paramètre est le type de retour de la fonction de rappel, ici c'est  None, ce qui signifie qu'il n'y a pas de valeur de retour ; le deuxième paramètre est le type de paramètre de la fonction de rappel, ici c'est  ctypes.c_int.

Nous avons ensuite défini une fonction de rappel en Python  my_callbackqui accepte un argument entier et imprime la valeur de cet argument dans la fonction.

Ensuite, nous  CallbackFunc convertissons la fonction de rappel Python en un type de pointeur de fonction  à l'aide de callback_func.

Enfin, nous chargeons la bibliothèque de liens dynamiques et appelons  register_callback la fonction, en passant le pointeur de fonction converti en paramètre à la fonction C.


 Comment obtenir des informations

【Message 777】

Amis qui souhaitent obtenir le code source et d'autres supports de didacticiel, veuillez aimer + commenter + collecter , trois fois de suite !

Après trois tours consécutifs , je vous enverrai des messages privés un par un dans la zone de commentaires~

Je suppose que tu aimes

Origine blog.csdn.net/GDYY3721/article/details/132210265
conseillé
Classement