Exercice 01 : Création et Compilation d'un Module C Simple
Objectif
Cet exercice a pour but de vous guider à travers les étapes complètes de création, compilation et utilisation d'une extension C simple pour Python. Vous allez implémenter un module systeminfo qui expose une fonction get_platform() retournant la plateforme du système d'exploitation sur laquelle Python a été compilé.
Contexte
L'API C de Python fournit des macros et des variables pour obtenir des informations sur le système. La macro Py_GetPlatform() retourne une chaîne de caractères (const char*) décrivant la plateforme (ex: "linux", "darwin" pour macOS, "win32" pour Windows).
Vous allez créer un module C qui rend cette information accessible directement depuis Python.
Prérequis
- Un compilateur C (GCC ou Clang sur Linux/macOS, MSVC sur Windows).
- Les en-têtes de développement Python.
- Sur Debian/Ubuntu :
sudo apt-get install python3-dev - Sur Fedora/CentOS :
sudo dnf install python3-devel - Sur macOS, ils sont généralement inclus avec les outils de ligne de commande Xcode.
- Sur Windows, assurez-vous de cocher "Python development headers" lors de l'installation de Python.
- Sur Debian/Ubuntu :
Énoncé
Étape 1 : Créer la structure du projet
Créez un nouveau dossier pour votre projet et placez-y deux fichiers vides :
systeminfo_module.csetup.py
Étape 2 : Écrire le code de l'extension C
Ouvrez systeminfo_module.c et écrivez le code C nécessaire. Inspirez-vous de l'exemple du cours.
- Inclure
Python.h. - Écrire la fonction C
systeminfo_get_platform.- Elle ne prend pas d'arguments, donc
PyObject* argsne sera pas utilisé. - Utilisez
Py_GetPlatform()pour obtenir la chaîne de caractères de la plateforme. - Utilisez
PyUnicode_FromString()pour convertir cette chaîne C en un objet chaîne de caractères Python. - Retournez cet objet Python.
- Elle ne prend pas d'arguments, donc
- Créer la table des méthodes
SystemInfoMethods.- Déclarez une seule méthode :
- Nom Python :
"get_platform" - Fonction C :
systeminfo_get_platform - Type d'appel :
METH_NOARGS(car la fonction ne prend pas d'arguments). - Docstring :
"Retourne la plateforme du système (ex: 'linux', 'darwin')."
- Nom Python :
- Déclarez une seule méthode :
- Créer la structure de définition du module
systeminfo_definition.- Nom du module :
"systeminfo" - Docstring du module :
"Un module d'exemple pour obtenir des informations système."
- Nom du module :
- Écrire la fonction d'initialisation
PyInit_systeminfo.
Étape 3 : Écrire le script de compilation
Ouvrez setup.py et écrivez le script pour distutils.
- Importez
setupetExtensiondepuisdistutils.core. - Créez un objet
Extension:- Nom du module :
"systeminfo" - Fichiers source :
['systeminfo_module.c']
- Nom du module :
- Appelez
setup()en lui passant les informations nécessaires, y compris votre objetExtensiondans la listeext_modules.
Étape 4 : Compiler et Installer le module
Ouvrez un terminal dans le dossier de votre projet.
-
Compiler le module.
python setup.py buildVérifiez qu'un dossier
builda été créé et qu'il contient votre bibliothèque partagée (.soou.pyd). -
Installer le module dans votre environnement de développement. Cette commande crée un lien symbolique vers le module compilé, ce qui vous permet de le tester sans avoir à le réinstaller après chaque modification.
python setup.py develop
Étape 5 : Tester le module en Python
-
Lancez un interpréteur Python depuis le même terminal.
-
Importez et utilisez votre module.
import systeminfo
# Testez la fonction
platform = systeminfo.get_platform()
print(f"La plateforme détectée par le module C est : '{platform}'")
# Vérifiez la docstring
print("\nDocstring du module:")
print(systeminfo.__doc__)
print("\nDocstring de la fonction:")
print(systeminfo.get_platform.__doc__)
Résultat Attendu
L'exécution du script de test Python doit afficher la plateforme de votre système, ainsi que les docstrings que vous avez définies dans votre code C.
La plateforme détectée par le module C est : 'darwin'
Docstring du module:
Un module d'exemple pour obtenir des informations système.
Docstring de la fonction:
Retourne la plateforme du système (ex: 'linux', 'darwin').
Cliquez ici pour voir un exemple de code de solution
Fichier systeminfo_module.c :
#define PY_SSIZE_T_CLEAN
#include <Python.h>
// 1. Implémentation de la fonction
static PyObject* systeminfo_get_platform(PyObject* self, PyObject* args) {
// Pas besoin de PyArg_ParseTuple car on n'a pas d'arguments (METH_NOARGS)
// Py_GetPlatform() retourne un const char*
const char* platform_str = Py_GetPlatform();
// Convertit la chaîne C en objet chaîne de caractères Python
return PyUnicode_FromString(platform_str);
}
// 2. Table des méthodes
static PyMethodDef SystemInfoMethods[] = {
{
"get_platform", // Nom en Python
systeminfo_get_platform, // Fonction C
METH_NOARGS, // Pas d'arguments
"Retourne la plateforme du système (ex: 'linux', 'darwin')." // Docstring
},
{NULL, NULL, 0, NULL} // Sentinelle
};
// 3. Définition du module
static struct PyModuleDef systeminfo_definition = {
PyModuleDef_HEAD_INIT,
"systeminfo", // Nom du module
"Un module d'exemple pour obtenir des informations système.", // Docstring
-1,
SystemInfoMethods
};
// 4. Fonction d'initialisation
PyMODINIT_FUNC PyInit_systeminfo(void) {
return PyModule_Create(&systeminfo_definition);
}
Fichier setup.py :
from distutils.core import setup, Extension
systeminfo_extension = Extension(
'systeminfo',
sources=['systeminfo_module.c']
)
setup(
name='SystemInfo',
version='1.0',
description='Module pour obtenir la plateforme système.',
ext_modules=[systeminfo_extension]
)