ctypes est une bibliothèque standard pour appeler des bibliothèques dynamiques à partir de Python. Notez les leçons / points auxquels vous étiez accro lorsque vous l'utilisiez pour la première fois récemment.
Lors de l'appel d'une fonction dans une bibliothèque dynamique, vous devez spécifier un type compatible avec C. (ref.) http://docs.python.jp/2/library/ctypes.html#ctypes-fundamental-data-types
Ce type est spécifié soit lorsque la fonction est appelée, soit la valeur de retour / le type d'argument est spécifié à l'avance par restype
/ ʻargtypes` avant l'appel.
Spécification de type
from ctypes import *
#Spécifié au moment de l'exécution
ret = test.func2(c_char_p("test"), c_char_p("test2"), c_char_p("test3"))
# restype/Spécifié par argtypes
test.func2.restype = c_char_p
test.func2.argtypes = (c_char_p, c_char_p, c_char_p)
ret = test.func2("test", "test2", "test3")
Puisqu'il devient gênant de spécifier à l'exécution au fur et à mesure que le nombre d'appels augmente, je pense qu'il est préférable de créer un module qui définit l'interface de la bibliothèque. Est-ce le même que le fichier d'en-tête C?
interface.py
from ctypes import *
test.func1.restype = c_int
test.func2.argtypes = (None)
test.func2.restype = c_char_p
test.func2.argtypes = (c_char_p, c_char_p, c_char_p)
Les structures sont représentées dans le monde Python par des classes qui héritent de ctypes.Structure
.
Les membres de la structure sont spécifiés dans les champs __fields__
comme un tableau de taples. Le taple doit être de la forme (<nom du champ>, <type>)
.
Structure et classe correspondante
from ctypes import *
class JSON_T(Structure):
__fields__ = [('type', c_int), ('refcount', c_size_t)]
Si vous souhaitez spécifier le type de pointeur de cette structure, utilisez la fonction ctypes.POINTER
.
(ref.)http://docs.python.jp/2/library/ctypes.html#ctypes.POINTER
Type de pointeur de structure
from ctypes import *
class JSON_T(Structure):
__fields__ = [('type', c_int), ('refcount', c_size_t)]
test.func3.restype = c_char_p
test.func3.argtypes = (c_void_p, c_char_p, c_char_p, c_char_p, POINTER(JSON_T))
Pour les types qui représentent à l'origine des pointeurs, tels que ctypes.c_char_p
et ctypes.c_void_p
, vous pouvez utiliser la fonction ctypes.POINTER
.
Type de pointeur de pointeur(À l'origine un type qui représente un pointeur)
from ctypes import *
test.func4.restype = c_char_p
test.func4.argtypes = (c_void_p, c_char_p, c_char_p, c_char_p, POINTER(c_void_p), POINTER(c_char_p))
Lors de leur utilisation, il est nécessaire de donner la variable spécifiée dans ctypes.c_char_p
/ ctypes.c_void_p
à la fonction ctypes.byref
pour obtenir une référence.
Gérer les arguments de type pointeur des pointeurs
from ctypes import *
test.func4.restype = c_char_p
test.func4.argtypes = (c_void_p, c_char_p, c_char_p, c_char_p, POINTER(c_void_p), POINTER(c_char_p))
#arg1 est déjà défini
arg2 = 'str2'
arg3 = 'str3'
arg4 = 'str4'
void_p_p = c_void_p(None)
char_p_p = c_char_p(None)
#S'il est en dessous, NULL est assigné au pointeur du pointeur, il est donc inutile.
# void_p_p = None
# char_p_p = None
test.func4(arg1, arg2, arg3, arg4, byref(void_p_p), byref(char_p_p))
(Note) Je ne connais pas les types qui représentent des types primitifs tels que ctypes.c_int
car je ne les ai pas utilisés cette fois. Utilisez-vous la fonction ctypes.POINTER
deux fois?
Recommended Posts