ctypes est une bibliothèque Python permettant d'accéder aux fonctions et symboles d'une bibliothèque externe (en particulier, codée en C).
Hello World!
Appel simple à printf de la libc :
>>> from ctypes import cdll
>>> libc=cdll.LoadLibrary('libc.so.6')
>>> libc.printf("Hello World!\n")
Hello World!
13
Définition du prototype (arguments et type de retour), exemple avec sqrt() de la bibliothèque mathématique :
>>> from ctypes import cdll, c_double
>>> libm = cdll.LoadLibrary('libm.so')
>>> sqrt = libm.sqrt
>>> sqrt.argtypes = (c_double,)
>>> sqrt.restype = c_double
>>> sqrt(4)
2.0
Pour les procédures, fonctions qui ne renvoient rien, utilisez « func.restype = None ».
Types
Entiers
- c_byte, c_ubyte
- c_short, c_ushort
- c_int, c_uint
- c_long, c_ulong
- c_longlong, c_ulonglong (n'existe pas toujours)
La taille des différents types dépendent du système d'exploitation et du processeur. Utilisez ctypes_stdint.py pour avoir des types de taille fixe.
Caractère
- c_char * équivalent du type C « char »
- c_char_p : équivalent du type C « char* »
- voir aussi create_string_buffer() (lire la section dédiée)
Pointeur
- c_char_p : char*
- c_void_p : void*
- POINTER(type) : type*
- Exemple : POINTER(c_int) : int*
On peut lire va valeur pointée avec « data.content » ou par son index : « data[0] » , « data[1] », ...
sizeof()
La fonction sizeof(type) calcule la taille d'un type en octets.
Pour définir une structure
from ctypes import Structure, Union, c_ulong, c_int, c_ushort
class user_regs_struct(Structure):
_fields_ = (
("ebx", c_ulong),
("ecx", c_ulong),
("edx", c_ulong),
("esi", c_ulong),
...
)
_sifields_t = (...)
class siginfo(Union):
_fields_ = (
("as_int", c_int),
("as_short", c_short),
...
)
On peut utiliser « _anonymous_ = ("_a", "_b", ...) » pour définir des champs anonymes dans une union.
Structure utilise l'endian de la machine. On peut indiquer l'endian de la structure en utilisant BigEndianStructure ou LittleEndianStructure.
Tableau d'octet (char*)
create_string_buffer(str) crée un tableau d'octets pouvant contenir des octets nuls :
from ctypes import create_string_buffer
python_string = "string with \0 byte"
c_string = create_string_buffer(python_string)
assert c_string.value == 'string with '
assert c_string.raw == python_string
create_string_buffer(int) crée un tampon de N octet pouvant contenir de octets nuls :
>>> from ctypes import create_string_buffer
>>> buffer = create_string_buffer(5)
>>> buffer.raw
'\x00\x00\x00\x00\x00'
c_char_p tronque au premier octet nul :
from ctypes import create_string_buffer
python_string = "string with \0 byte"
c_string = c_char_p(python_string)
assert c_string.value == 'string with '
Charger une bibliothèque
Exemple simple :
from ctypes import cdll
libm = cdll.LoadLibrary('libm.so')
Pour trouver une bibliothèque, on peut utiliser :
from ctypes import cdll
from ctypes.util import find_library
LIBC_FILENAME = find_library('c')
libc = cdll.LoadLibrary(LIBC_FILENAME)
C'est la techhique utilisée par ctypes_libc.py pour charger bibliothèque C de façon portable (testé sous Linux, FreeBSD et Mac OS X).
Modules
ctypes_errno.py : lire la variable errno, code d'erreur C
ctypes_tools.py : outils divers
Outils connexes :
cpu_info.py : informations sur le processeur
os_tools.py : informations sur le système d'exploitation
Liens externes
pynetfilter_conntrack : binding Python de la bibliothèque libnetfilter_conntrack (pilotage du parefeu Linux)
python-ptrace : binding Python de la bibliothèque ptrace (débogueur de processus dans le noyau)