0Pricing
Python Academy · Leçon

Écrire un module d’extension C pour Python

Créez une extension .so simple avec l’API Python/C.

Écrire un module d’extension C pour Python est une leçon Python Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Python Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Python Academy comprend 4 leçons au total.

Anatomie d’une extension C

Une extension C minimale comprend : des fonctions de méthode, une table des méthodes, une structure de définition du module et un point d’entrée PyInit_.

// myext.c skeleton
#include <Python.h>

static PyObject* say_hello(PyObject* self, PyObject* args) {
    Py_RETURN_NONE;
}

static PyMethodDef methods[] = {
    {"say_hello", say_hello, METH_NOARGS, "Print hello"},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef module = {
    PyModuleDef_HEAD_INIT, "myext", NULL, -1, methods
};

PyMODINIT_FUNC PyInit_myext(void) {
    return PyModule_Create(&module);
}

Analyser les arguments

PyArg_ParseTuple(args, "ii", &a, &b) analyse les arguments Python pour les placer dans des variables C. Codes de format : i=int, d=double, s=char*, O=PyObject*.

static PyObject* add(PyObject* self, PyObject* args) {
    int a, b;
    if (!PyArg_ParseTuple(args, "ii", &a, &b))
        return NULL;
    return PyLong_FromLong(a + b);
}

Renvoyer des valeurs

Construisez les valeurs de retour Python avec : PyLong_FromLong, PyFloat_FromDouble, PyUnicode_FromString, Py_BuildValue.

// Return a Python tuple (int, float)
static PyObject* stats(PyObject* self, PyObject* args) {
    int n = 10;
    double avg = 5.0;
    return Py_BuildValue("(id)", n, avg);
    // Py_BuildValue format: i=int d=double s=str
}

Comptage des références

Chaque PyObject* possède un compteur de références. Utilisez Py_INCREF/Py_DECREF avec précaution. Les valeurs renvoyées par les fonctions C transfèrent la propriété à l’appelant (références volées).

static PyObject* make_list(PyObject* self, PyObject* args) {
    PyObject* lst = PyList_New(3);
    for (int i = 0; i < 3; i++) {
        // PyList_SET_ITEM steals the reference:
        PyList_SET_ITEM(lst, i, PyLong_FromLong(i));
    }
    return lst;   // caller owns the list
}

Lever des exceptions

Utilisez PyErr_SetString(PyExc_ValueError, "msg") pour lever une exception Python depuis C, puis renvoyez NULL.

static PyObject* safe_div(PyObject* self, PyObject* args) {
    int a, b;
    if (!PyArg_ParseTuple(args, "ii", &a, &b)) return NULL;
    if (b == 0) {
        PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
        return NULL;
    }
    return PyLong_FromLong(a / b);
}

setup.py pour les extensions C

Utilisez setuptools.Extension pour déclarer les fichiers source C. Compilez avec python setup.py build_ext --inplace.

# setup.py
from setuptools import setup, Extension

setup(
    name="myext",
    ext_modules=[
        Extension(
            "myext",
            sources=["myext.c"],
            extra_compile_args=["-O2"],
        )
    ]
)
# python setup.py build_ext --inplace
# import myext; myext.add(3, 4)

Utiliser l’extension compilée

Une fois compilée, importez l’extension comme n’importe quel module Python. Python la trouve en recherchant myext.so (ou .pyd sous Windows).

# After: python setup.py build_ext --inplace
import myext
print(myext.add(3, 4))        # 7
print(myext.safe_div(10, 2))  # 5
# myext.safe_div(1, 0)         # ZeroDivisionError

Arguments nommés

Utilisez PyArg_ParseTupleAndKeywords avec une liste de mots-clés pour prendre en charge les arguments nommés dans les fonctions C.

static char* kwargs[] = {"x", "y", NULL};

static PyObject* hypot_c(PyObject* self,
                          PyObject* args,
                          PyObject* kw) {
    double x, y;
    if (!PyArg_ParseTupleAndKeywords(args, kw, "dd",
                                     kwargs, &x, &y))
        return NULL;
    return PyFloat_FromDouble(sqrt(x*x + y*y));
}

Constantes au niveau du module

Ajoutez des constantes entières ou chaînes au module dans PyInit_ à l’aide de PyModule_AddIntConstant.

PyMODINIT_FUNC PyInit_myext(void) {
    PyObject* m = PyModule_Create(&module);
    if (!m) return NULL;
    PyModule_AddIntConstant(m, "VERSION", 1);
    PyModule_AddStringConstant(m, "AUTHOR", "Alice");
    return m;
}

Libérer le GIL

Entourez le travail effectué uniquement en C avec Py_BEGIN_ALLOW_THREADS / Py_END_ALLOW_THREADS afin de permettre l’exécution d’autres threads Python pendant l’exécution du code C.

static PyObject* heavy(PyObject* self, PyObject* args) {
    long n;
    if (!PyArg_ParseTuple(args, "l", &n)) return NULL;
    long result;
    Py_BEGIN_ALLOW_THREADS
        result = slow_c_computation(n);  // GIL released
    Py_END_ALLOW_THREADS
    return PyLong_FromLong(result);
}

Tester l’extension

Testez les extensions C via leur interface Python avec pytest. Aucun outil de test C particulier n’est nécessaire.

# test_myext.py
import pytest
import myext

def test_add(): assert myext.add(3, 4) == 7
def test_zero_div():
    with pytest.raises(ZeroDivisionError):
        myext.safe_div(1, 0)

Vérification rapide

Que doit renvoyer une fonction d’extension C pour signaler qu’une exception Python a été définie ?

Récapitulatif

Une extension C nécessite : des fonctions de méthode (analyse des arguments, retour d’un PyObject*), une table des méthodes, une structure de définition du module et PyInit_name(). Levez les exceptions en les définissant avec PyErr_SetString, puis en renvoyant NULL. Libérez le GIL pour le travail effectué uniquement en C.

Questions Fréquemment Posées

La leçon « Écrire un module d’extension C pour Python » est-elle gratuite ?

Oui — le texte complet de « Écrire un module d’extension C pour Python » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Python Academy, passe à CoddyKit PRO. Le cours Python Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Écrire un module d’extension C pour Python » ?

Créez une extension .so simple avec l’API Python/C. Tu pratiques Python Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Python Academy ?

Aucune expérience préalable n'est requise. Python Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.

Combien de temps prend la leçon « Écrire un module d’extension C pour Python » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Python Academy ?

Oui. Chaque leçon Python Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Pourquoi les extensions C ? Cas d’usage et compromis
  2. ctypes : appeler des bibliothèques C depuis Python
  3. cffi : interface de fonctions externes C
  4. Écrire un module d’extension C pour Python
← Retour à Python Academy