Using the C API: Assorted topics
********************************

The tutorial walked you through creating a C API extension module, but
left many areas unexplained. This document looks at several concepts
that you'll need to learn in order to write more complex extensions.


Errors and Exceptions
=====================

Une convention importante dans l'interpréteur Python est la suivante :
lorsqu'une fonction échoue, elle doit définir une condition
d'exception et renvoyer une valeur d'erreur (généralement "-1" ou un
pointeur "NULL"). Les informations d'exception sont stockées dans
trois attributs de l'état du thread de l'interpréteur. Ils valent
"NULL" s'il n'y a pas d'exception. Sinon, ce sont les équivalents C
des membres du *n*-uplet Python renvoyé par "sys.exc_info()". Il
s'agit du type d'exception, de l'instance d'exception et d'un objet de
trace. Il est important de les connaître pour comprendre comment les
erreurs sont transmises.

L'API Python définit un certain nombre de fonctions pour créer
différents types d'exceptions.

La plus courante est "PyErr_SetString()". Ses arguments sont un objet
exception et une chaîne C. L'objet exception est généralement un objet
prédéfini comme "PyExc_ZeroDivisionError". La chaîne C indique la
cause de l'erreur et est convertie en une chaîne Python puis stockée
en tant que « valeur associée » à l'exception.

Une autre fonction utile est "PyErr_SetFromErrno()", qui construit une
exception à partir de la valeur de la variable globale "errno". La
fonction la plus générale est "PyErr_SetObject()", qui prend deux
arguments : l'exception et sa valeur associée. Vous ne devez pas
appliquer "Py_INCREF()" aux objets transmis à ces fonctions.

Vous pouvez tester de manière non destructive si une exception a été
levée avec "PyErr_Occurred()". Cela renvoie l'objet exception actuel,
ou "NULL" si aucune exception n'a eu lieu. Cependant, vous ne devriez
pas avoir besoin d'appeler "PyErr_Occurred()" pour voir si une erreur
est survenue durant l'appel d'une fonction, puisque vous devriez être
en mesure de le déterminer à partir de la valeur renvoyée.

Lorsqu'une fonction *f* ayant appelé une autre fonction *g* détecte
que cette dernière a échoué, *f* devrait donner une valeur d'erreur à
son tour (habituellement "NULL" ou "-1"). La fonction *f* ne devrait
*pas* appeler l'une des fonctions "PyErr_*", l'une d'entre elles ayant
déjà été appelée par *g*. La fonction appelant *f* est alors censée
renvoyer aussi un code d'erreur à celle qui l'a appelée, toujours sans
utiliser "PyErr_*", et ainsi de suite. La cause la plus détaillée de
l'erreur a déjà été signalée par la fonction l'ayant détecté en
premier. Une fois l'erreur remontée à la boucle principale de
l'interpréteur Python, il interrompt le code en cours d'exécution et
essaie de trouver un gestionnaire d'exception spécifié par le
développeur Python.

(Il y a des situations où un module peut effectivement donner un
message d'erreur plus détaillé en appelant une autre fonction
"PyErr_*" et, dans de tels cas, il est tout à fait possible de le
faire. Cependant, ce n'est généralement pas nécessaire, et peut amener
à perdre des informations sur la cause de l'erreur : la plupart des
opérations peuvent échouer pour tout un tas de raisons.)

Pour ignorer une exception qui aurait été émise lors d'un appel de
fonction qui a échoué, l'exception doit être retirée explicitement en
appelant "PyErr_Clear()". Le seul cas pour lequel du code C devrait
appeler "PyErr_Clear()" est lorsqu'il ne veut pas passer l'erreur à
l'interpréteur, mais souhaite la gérer lui-même (peut-être en essayant
quelque chose d'autre, ou en prétendant que rien n'a mal tourné).

Chaque échec de "malloc()" doit être transformé en une exception,
l'appelant direct de "malloc()" (ou "realloc()") doit appeler
"PyErr_NoMemory()" et prendre l'initiative de renvoyer une valeur
d'erreur. Toutes les fonctions construisant des objets (tels que
"PyLong_FromLong()") le font déjà, donc cette note ne concerne que
ceux qui appellent "malloc()" directement.

Notez également que, à l'exception notable de "PyArg_ParseTuple()" et
compagnie, les fonctions qui renvoient leur statut sous forme d'entier
donnent généralement une valeur positive ou zéro en cas de succès et
"-1" en cas d'échec, comme les appels du système Unix.

Enfin, lorsque vous renvoyez un code d'erreur, n'oubliez pas faire un
brin de nettoyage (en appelant "Py_XDECREF()" ou "Py_DECREF()" avec
les objets que vous auriez déjà créés) !

The choice of which exception to raise is entirely yours.  There are
predeclared C objects corresponding to all built-in Python exceptions,
such as "PyExc_ZeroDivisionError", which you can use directly. Of
course, you should choose exceptions wisely --- don't use
"PyExc_TypeError" to mean that a file couldn't be opened (that should
probably be "PyExc_OSError"). If something's wrong with the argument
list, the "PyArg_ParseTuple()" function usually raises
"PyExc_TypeError".  If you have an argument whose value must be in a
particular range or must satisfy other conditions, "PyExc_ValueError"
is appropriate.

You can also define a new exception that is unique to your module. The
simplest way to do this is to declare a static global object variable
at the beginning of the file:

   static PyObject *SpamError = NULL;

and initialize it by calling "PyErr_NewException()" in the module's
"Py_mod_exec" function ("spam_module_exec()"):

   SpamError = PyErr_NewException("spam.error", NULL, NULL);

Since "SpamError" is a global variable, it will be overwritten every
time the module is reinitialized, when the "Py_mod_exec" function is
called.

For now, let's avoid the issue: we will block repeated initialization
by raising an "ImportError":

   static PyObject *SpamError = NULL;

   static int
   spam_module_exec(PyObject *m)
   {
       if (SpamError != NULL) {
           PyErr_SetString(PyExc_ImportError,
                           "cannot initialize spam module more than once");
           return -1;
       }
       SpamError = PyErr_NewException("spam.error", NULL, NULL);
       if (PyModule_AddObjectRef(m, "SpamError", SpamError) < 0) {
           return -1;
       }

       return 0;
   }

   static PyModuleDef_Slot spam_module_slots[] = {
       {Py_mod_exec, spam_module_exec},
       {0, NULL}
   };

   static struct PyModuleDef spam_module = {
       .m_base = PyModuleDef_HEAD_INIT,
       .m_name = "spam",
       .m_size = 0,  // non-negative
       .m_slots = spam_module_slots,
   };

   PyMODINIT_FUNC
   PyInit_spam(void)
   {
       return PyModuleDef_Init(&spam_module);
   }

Note that the Python name for the exception object is "spam.error".
The "PyErr_NewException()" function may create a class with the base
class being "Exception" (unless another class is passed in instead of
"NULL"), described in Exceptions natives.

Notez également que la variable "SpamError" contient une référence à
la nouvelle classe créée ; ceci est intentionnel ! Comme l'exception
peut être enlevée du module par du code externe, une référence à la
classe est nécessaire pour assurer qu'elle ne sera pas supprimée par
le ramasse-miettes, entraînant que "SpamError" devienne un pointeur
dans le vide. Si cela se produisait, le code C qui lève cette
exception peut engendrer un *core dump* ou des effets secondaires
inattendus.

For now, the "Py_DECREF()" call to remove this reference is missing.
Even when the Python interpreter shuts down, the global "SpamError"
variable will not be garbage-collected. It will "leak". We did,
however, ensure that this will happen at most once per process.

We discuss the use of "PyMODINIT_FUNC" as a function return type later
in this sample.

The "spam.error" exception can be raised in your extension module
using a call to "PyErr_SetString()" as shown below:

   static PyObject *
   spam_system(PyObject *self, PyObject *args)
   {
       const char *command;
       int sts;

       if (!PyArg_ParseTuple(args, "s", &command))
           return NULL;
       sts = system(command);
       if (sts < 0) {
           PyErr_SetString(SpamError, "System command failed");
           return NULL;
       }
       return PyLong_FromLong(sts);
   }


Embedding an extension
======================

If you want to make your module a permanent part of the Python
interpreter, you will have to change the configuration setup and
rebuild the interpreter.  On Unix, place your file ("spammodule.c" for
example) in the "Modules/" directory of an unpacked source
distribution, add a line to the file "Modules/Setup.local" describing
your file:

   spam spammodule.o

et reconstruisez l'interpréteur en exécutant **make** dans le
répertoire de niveau supérieur. Vous pouvez également exécuter
**make** dans le sous-répertoire "Modules/", mais vous devez d'abord
reconstruire le "Makefile" en exécutant « **make** Makefile » (c'est
nécessaire chaque fois que vous modifiez le fichier "Setup").

Si votre module nécessite d'être lié à des bibliothèques
supplémentaires, celles-ci peuvent être ajoutées à la fin de la ligne
de votre module dans le fichier de configuration, par exemple :

   spam spammodule.o -lX11


Appeler des fonctions Python en C
=================================

The tutorial concentrated on making C functions callable from Python.
The reverse is also useful: calling Python functions from C. This is
especially the case for libraries that support so-called "callback"
functions.  If a C interface makes use of callbacks, the equivalent
Python often needs to provide a callback mechanism to the Python
programmer; the implementation will require calling the Python
callback functions from a C callback.  Other uses are also imaginable.

Heureusement, l'interpréteur Python est facilement appelé de manière
récursive et il existe une interface standard pour appeler une
fonction Python (nous ne nous attarderons pas sur la façon d'appeler
l'analyseur Python avec une chaîne particulière en entrée — si vous
êtes intéressé, jetez un œil à l'implémentation de l'option de ligne
de commande "-c" dans "Modules/main.c" à partir du code source
Python).

L'appel d'une fonction Python est facile. Tout d'abord, le programme
Python doit vous transmettre d'une manière ou d'une autre l'objet de
fonction Python. Vous devez fournir une fonction (ou une autre
interface) pour ce faire. Lorsque cette fonction est appelée,
enregistrez un pointeur vers l'objet de la fonction Python (faites
attention à "Py_INCREF()" !) dans une variable globale — ou là où vous
le souhaitez. Par exemple, la fonction suivante peut faire partie
d'une définition de module :

   static PyObject *my_callback = NULL;

   static PyObject *
   my_set_callback(PyObject *dummy, PyObject *args)
   {
       PyObject *result = NULL;
       PyObject *temp;

       if (PyArg_ParseTuple(args, "O:set_callback", &temp)) {
           if (!PyCallable_Check(temp)) {
               PyErr_SetString(PyExc_TypeError, "parameter must be callable");
               return NULL;
           }
           Py_XINCREF(temp);         /* Add a reference to new callback */
           Py_XDECREF(my_callback);  /* Dispose of previous callback */
           my_callback = temp;       /* Remember new callback */
           /* Boilerplate to return "None" */
           Py_INCREF(Py_None);
           result = Py_None;
       }
       return result;
   }

This function must be registered with the interpreter using the
"METH_VARARGS" flag in "PyMethodDef.ml_flags".  The
"PyArg_ParseTuple()" function and its arguments are documented in
section Extraire des paramètres dans des fonctions d'extension.

Les macros "Py_XINCREF()" et "Py_XDECREF()" incrémentent/décrémentent
le compteur des références d'un objet et sont sûres quant à la
présence de pointeurs "NULL" (mais notez que *temp* ne sera pas "NULL"
dans ce contexte).  Plus d'informations à ce sujet dans la section
Compteurs de références.

Plus tard, quand il est temps d'appeler la fonction, vous appelez la
fonction C "PyObject_CallObject()". Cette fonction requiert deux
arguments, tous deux des pointeurs vers des objets Python arbitraires
: la fonction Python et la liste d'arguments. La liste d'arguments
doit toujours être un objet *n*-uplet, dont la longueur est le nombre
d'arguments. Pour appeler la fonction Python sans argument, passez
"NULL" ou le *n*-uplet vide ; pour l'appeler avec un argument, passez
un *n*-uplet singleton. "Py_BuildValue()" renvoie un *n*-uplet lorsque
sa chaîne de format se compose de zéro ou plusieurs codes de format
entre parenthèses. Par exemple :

   int arg;
   PyObject *arglist;
   PyObject *result;
   ...
   arg = 123;
   ...
   /* Time to call the callback */
   arglist = Py_BuildValue("(i)", arg);
   result = PyObject_CallObject(my_callback, arglist);
   Py_DECREF(arglist);

"PyObject_CallObject()" renvoie un pointeur d'objet Python : c'est la
valeur de retour de la fonction Python. "PyObject_CallObject()" est «
neutre en nombre de références » par rapport à ses arguments. Dans
l'exemple, un nouveau *n*-uplet a été créé pour servir de liste
d'arguments, qui est décrémenté (avec "Py_DECREF()") immédiatement
après l'appel "PyObject_CallObject()".

La valeur de retour de "PyObject_CallObject()" est « nouvelle » : soit
c'est un tout nouvel objet, soit c'est un objet existant dont le
nombre de références a été incrémenté. Donc, à moins que vous ne
vouliez l'enregistrer dans une variable globale, vous devriez en
quelque sorte décrémenter avec "Py_DECREF()" le résultat, même
(surtout !) si vous n'êtes pas intéressé par sa valeur.

Mais avant de le faire, il est important de vérifier que la valeur
renvoyée n'est pas "NULL".  Si c'est le cas, la fonction Python s'est
terminée par une levée d'exception. Si le code C qui a appelé
"PyObject_CallObject()" est appelé depuis Python, il devrait
maintenant renvoyer une indication d'erreur à son appelant Python,
afin que l'interpréteur puisse afficher la pile d'appels, ou que le
code Python appelant puisse gérer l'exception. Si cela n'est pas
possible ou souhaitable, l'exception doit être effacée en appelant
"PyErr_Clear()". Par exemple :

   if (result == NULL)
       return NULL; /* Pass error back */
   ...use result...
   Py_DECREF(result);

Selon l'interface souhaitée pour la fonction de rappel Python, vous
devrez peut-être aussi fournir une liste d'arguments à
"PyObject_CallObject()". Dans certains cas, la liste d'arguments est
également fournie par le programme Python, par l'intermédiaire de la
même interface qui a spécifié la fonction de rappel. Elle peut alors
être sauvegardée et utilisée de la même manière que l'objet fonction.
Dans d'autres cas, vous pouvez avoir à construire un nouveau *n*-uplet
à passer comme liste d'arguments. La façon la plus simple de faire
cela est d'appeler "Py_BuildValue()". Par exemple, si vous voulez
passer un code d'événement intégral, vous pouvez utiliser le code
suivant :

   PyObject *arglist;
   ...
   arglist = Py_BuildValue("(l)", eventcode);
   result = PyObject_CallObject(my_callback, arglist);
   Py_DECREF(arglist);
   if (result == NULL)
       return NULL; /* Pass error back */
   /* Here maybe use the result */
   Py_DECREF(result);

Notez la présence de "Py_DECREF(arglist)" immédiatement après l'appel,
avant la vérification des erreurs ! Notez également qu'à proprement
parler, ce code n'est pas complet : "Py_BuildValue()" peut manquer de
mémoire, et cela doit être vérifié.

Vous pouvez également appeler une fonction avec des arguments nommés
en utilisant "PyObject_Call()", qui accepte les arguments et les
arguments nommés. Comme dans l'exemple ci-dessus, nous utilisons
"Py_BuildValue()" pour construire le dictionnaire.

   PyObject *dict;
   ...
   dict = Py_BuildValue("{s:i}", "name", val);
   result = PyObject_Call(my_callback, NULL, dict);
   Py_DECREF(dict);
   if (result == NULL)
       return NULL; /* Pass error back */
   /* Here maybe use the result */
   Py_DECREF(result);


Extraire des paramètres dans des fonctions d'extension
======================================================

The tutorial uses a ""METH_O"" function, which is limited to a single
Python argument. If you want more, you can use "METH_VARARGS" instead.
With this flag, the C function will receive a "tuple" of arguments
instead of a single object.

For unpacking the tuple, CPython provides the "PyArg_ParseTuple()"
function, declared as follows:

   int PyArg_ParseTuple(PyObject *arg, const char *format, ...);

L'argument *arg* doit être un *n*-uplet contenant une liste
d'arguments passée de Python à une fonction C. L'argument *format*
doit être une chaîne de format, dont la syntaxe est expliquée dans
Analyse des arguments et construction des valeurs dans le manuel de
référence de l'API Python/C. Les arguments restants doivent être des
adresses de variables dont le type est déterminé par la chaîne de
format.

For example, to receive a single Python "str" object and turn it into
a C buffer, you would use ""s"" as the format string:

   const char *command;
   if (!PyArg_ParseTuple(args, "s", &command)) {
       return NULL;
   }

If an error is detected in the argument list, "PyArg_ParseTuple()"
returns "NULL" (the error indicator for functions returning object
pointers); your function may return "NULL", relying on the exception
set by "PyArg_ParseTuple()".

Notez que si "PyArg_ParseTuple()" vérifie que les arguments Python ont
les types requis, elle ne peut pas vérifier la validité des adresses
des variables C transmises à l'appel : si vous y faites des erreurs,
votre code plantera probablement ou au moins écrasera des bits
aléatoires en mémoire. Donc soyez prudent !

Notez que toute référence sur un objet Python donnée à l'appelant est
une référence *empruntée* ; ne décrémentez pas son compteur de
références !

Quelques exemples d'appels :

   #include <Python.h>

   int ok;
   int i, j;
   long k, l;
   const char *s;
   Py_ssize_t size;

   ok = PyArg_ParseTuple(args, ""); /* No arguments */
       /* Python call: f() */

   ok = PyArg_ParseTuple(args, "s", &s); /* A string */
       /* Possible Python call: f('whoops!') */

   ok = PyArg_ParseTuple(args, "lls", &k, &l, &s); /* Two longs and a string */
       /* Possible Python call: f(1, 2, 'three') */

   ok = PyArg_ParseTuple(args, "(ii)s#", &i, &j, &s, &size);
       /* A pair of ints and a string, whose size is also returned */
       /* Possible Python call: f((1, 2), 'three') */

   {
       const char *file;
       const char *mode = "r";
       int bufsize = 0;
       ok = PyArg_ParseTuple(args, "s|si", &file, &mode, &bufsize);
       /* A string, and optionally another string and an integer */
       /* Possible Python calls:
          f('spam')
          f('spam', 'w')
          f('spam', 'wb', 100000) */
   }

   {
       int left, top, right, bottom, h, v;
       ok = PyArg_ParseTuple(args, "((ii)(ii))(ii)",
                &left, &top, &right, &bottom, &h, &v);
       /* A rectangle and a point */
       /* Possible Python call:
          f(((0, 0), (400, 300)), (10, 10)) */
   }

   {
       Py_complex c;
       ok = PyArg_ParseTuple(args, "D:myfunction", &c);
       /* a complex, also providing a function name for errors */
       /* Possible Python call: myfunction(1+2j) */
   }


Paramètres nommés pour des fonctions d'extension
================================================

If you also want your function to accept *keyword arguments*, use the
"METH_KEYWORDS" flag in combination with "METH_VARARGS".
("METH_KEYWORDS" can also be used with other flags; see its
documentation for the allowed combinations.)

In this case, the C function should accept a third "PyObject *"
parameter which will be a dictionary of keywords. Use
"PyArg_ParseTupleAndKeywords()" to parse the arguments to such a
function.

La fonction "PyArg_ParseTupleAndKeywords()" est déclarée ainsi :

   int PyArg_ParseTupleAndKeywords(PyObject *arg, PyObject *kwdict,
                                   const char *format, char * const *kwlist, ...);

Les paramètres *arg* et *format* sont identiques à ceux de la fonction
"PyArg_ParseTuple()". Le paramètre *kwdict* est le dictionnaire de
mots-clés reçu comme troisième paramètre du *runtime* Python. Le
paramètre *kwlist* est une liste de chaînes de caractères terminée par
"NULL" qui identifie les paramètres ; les noms sont mis en
correspondance, de gauche à droite, avec les informations de type de
*format*. En cas de succès du processus,
"PyArg_ParseTupleAndKeywords()" renvoie vrai, sinon elle renvoie faux
et lève une exception appropriée.

Note:

  les *n*-uplets imbriqués ne peuvent pas être traités lorsqu'on
  utilise des arguments nommés ! Ceux-ci doivent apparaître dans
  *kwlist*, dans le cas contraire une exception "TypeError" est levée.

Voici un exemple de module qui utilise des arguments nommés, basé sur
un exemple de *Geoff Philbrick* (philbrick@hks.com) :

   #define PY_SSIZE_T_CLEAN
   #include <Python.h>

   static PyObject *
   keywdarg_parrot(PyObject *self, PyObject *args, PyObject *keywds)
   {
       int voltage;
       const char *state = "a stiff";
       const char *action = "voom";
       const char *type = "Norwegian Blue";

       static char *kwlist[] = {"voltage", "state", "action", "type", NULL};

       if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|sss", kwlist,
                                        &voltage, &state, &action, &type))
           return NULL;

       printf("-- This parrot wouldn't %s if you put %i Volts through it.\n",
              action, voltage);
       printf("-- Lovely plumage, the %s -- It's %s!\n", type, state);

       Py_RETURN_NONE;
   }

   static PyMethodDef keywdarg_methods[] = {
       /* The cast of the function is necessary since PyCFunction values
        * only take two PyObject* parameters, and keywdarg_parrot() takes
        * three.
        */
       {"parrot", (PyCFunction)(void(*)(void))keywdarg_parrot, METH_VARARGS | METH_KEYWORDS,
        "Print a lovely skit to standard output."},
       {NULL, NULL, 0, NULL}   /* sentinel */
   };


Créer des valeurs arbitraires
=============================

Cette fonction est le complément de "PyArg_ParseTuple()".  Elle est
déclarée comme suit :

   PyObject *Py_BuildValue(const char *format, ...);

Elle reconnaît un ensemble d'unités de format similaires à celles
reconnues par "PyArg_ParseTuple()", mais les arguments (qui sont les
données en entrée de la fonction, et non de la sortie) ne doivent pas
être des pointeurs, mais juste des valeurs. Elle renvoie un nouvel
objet Python, adapté pour être renvoyé par une fonction C appelée
depuis Python.

Une différence avec "PyArg_ParseTuple()" : alors que cette dernière
nécessite que son premier argument soit un *n*-uplet (puisque les
listes d'arguments Python sont toujours représentées comme des
*n*-uplets en interne), "Py_BuildValue()" ne construit pas toujours un
*n*-uplet. Elle construit un *n*-uplet uniquement si sa chaîne de
format contient deux unités de format ou plus. Si la chaîne de format
est vide, elle renvoie "None" ; si elle contient exactement une unité
de format, elle renvoie tout objet décrit par cette unité de format.
Pour la forcer à renvoyer un *n*-uplet de taille 0 ou un, mettez la
chaîne de format entre parenthèses.

Exemples (à gauche l'appel, à droite la valeur résultante, en Python)
:

   Py_BuildValue("")                        None
   Py_BuildValue("i", 123)                  123
   Py_BuildValue("iii", 123, 456, 789)      (123, 456, 789)
   Py_BuildValue("s", "hello")              'hello'
   Py_BuildValue("y", "hello")              b'hello'
   Py_BuildValue("ss", "hello", "world")    ('hello', 'world')
   Py_BuildValue("s#", "hello", 4)          'hell'
   Py_BuildValue("y#", "hello", 4)          b'hell'
   Py_BuildValue("()")                      ()
   Py_BuildValue("(i)", 123)                (123,)
   Py_BuildValue("(ii)", 123, 456)          (123, 456)
   Py_BuildValue("(i,i)", 123, 456)         (123, 456)
   Py_BuildValue("[i,i]", 123, 456)         [123, 456]
   Py_BuildValue("{s:i,s:i}",
                 "abc", 123, "def", 456)    {'abc': 123, 'def': 456}
   Py_BuildValue("((ii)(ii)) (ii)",
                 1, 2, 3, 4, 5, 6)          (((1, 2), (3, 4)), (5, 6))


Compteurs de références
=======================

Dans les langages comme le C ou le C++, le développeur est responsable
de l'allocation dynamique et de la dés-allocation de la mémoire sur le
tas. En C, cela se fait à l'aide des fonctions "malloc()" et "free()".
En C++, les opérateurs  "new" et "delete"  sont utilisés avec
essentiellement la même signification et nous limiterons la discussion
suivante au cas du C.

Every block of memory allocated with "malloc()" should eventually be
returned to the pool of available memory by exactly one call to
"free()". It is important to call "free()" at the right time.  If a
block's address is forgotten but "free()" is not called for it, the
memory it occupies cannot be reused until the program terminates.
This is called a *memory leak*.  On the other hand, if a program calls
"free()" for a block and then continues to use the block, it creates a
conflict with reuse of the block through another "malloc()" call.
This is called *using freed memory*. It has the same bad consequences
as referencing uninitialized data --- core dumps, wrong results,
mysterious crashes.

Les causes courantes des fuites de mémoire sont des exécutions
inhabituelles du code. Par exemple, une fonction peut allouer un bloc
de mémoire, effectuer des calculs, puis libérer le bloc. Plus tard,
une modification des exigences de la fonction peut ajouter un test au
calcul qui détecte une condition d'erreur et peut sortir prématurément
de la fonction. Il est facile d'oublier de libérer le bloc de mémoire
alloué lors de cette sortie prématurée, surtout lorsqu'elle est
ajoutée ultérieurement au code. De telles fuites, une fois
introduites, passent souvent inaperçues pendant longtemps : la sortie
d'erreur n'est prise que dans une petite fraction de tous les appels,
et la plupart des machines modernes ont beaucoup de mémoire virtuelle,
de sorte que la fuite ne devient apparente que dans un processus de
longue durée qui utilise fréquemment cette fonction. Par conséquent,
il est important d'éviter les fuites en ayant une convention ou une
stratégie de codage qui minimise ce type d'erreurs.

Comme Python fait un usage intensif de "malloc()" et de "free()", il a
besoin d'une stratégie pour éviter les fuites de mémoire ainsi que
l'utilisation de la mémoire libérée. La méthode choisie est appelée le
*comptage de références*. Le principe est simple : chaque objet
contient un compteur, qui est incrémenté lorsqu'une référence à
l'objet est stockée quelque part, et qui est décrémenté lorsqu'une
référence à celui-ci est supprimée. Lorsque le compteur atteint zéro,
la dernière référence à l'objet a été supprimée et l'objet est libéré.

Une stratégie alternative est appelée *ramasse-miettes automatique*
(*automatic garbage collection* en anglais). Parfois, le comptage des
références est également appelé stratégie de ramasse-miettes, d'où
l'utilisation du terme « automatique » pour distinguer les deux. Le
grand avantage du ramasse-miettes est que l'utilisateur n'a pas besoin
d'appeler "free()" explicitement (un autre avantage important est
l'amélioration de la vitesse ou de l'utilisation de la mémoire, ce
n'est cependant pas un fait avéré). L'inconvénient est que pour C, il
n'y a pas de ramasse-miettes portable proprement-dit, alors que le
comptage des références peut être implémenté de façon portable (tant
que les fonctions "malloc()" et "free()" sont disponibles, ce que la
norme C garantit). Peut-être qu'un jour un ramasse-miettes
suffisamment portable sera disponible pour C. D'ici là, nous devons
utiliser les compteurs de références.

Bien que Python utilise l'implémentation traditionnelle de comptage de
références, il contient également un détecteur de cycles qui
fonctionne pour détecter les cycles de références. Cela permet aux
applications de ne pas se soucier de la création de références
circulaires directes ou indirectes ; celles-ci sont les faiblesses des
ramasse-miettes utilisant uniquement le comptage de références. Les
cycles de références sont constitués d'objets qui contiennent des
références (éventuellement indirectes) à eux-mêmes, de sorte que
chaque objet du cycle a un compteur de références qui n'est pas nul.
Les implémentations typiques de comptage de références ne sont pas
capables de récupérer la mémoire des objets appartenant à un cycle de
références, ou référencés à partir des objets dans le cycle, même s'il
n'y a pas d'autre référence au cycle lui-même.

Le détecteur de cycle est capable de détecter les cycles isolés et
peut récupérer la mémoire afférente. Le module "gc" expose un moyen
d'exécuter le détecteur (la fonction "collect()"), ainsi que des
interfaces de configuration et la possibilité de désactiver le
détecteur au moment de l'exécution.


Comptage de références en Python
--------------------------------

Il existe deux macros, "Py_INCREF(x)" et "Py_DECREF(x)", qui gèrent
l'incrémentation et la décrémentation du comptage de références.
"Py_DECREF()" libère également l'objet lorsque le compteur atteint
zéro. Pour plus de flexibilité, il n'appelle pas "free()" directement
— plutôt, il fait un appel à travers un pointeur de fonction dans
l'objet *type objet* de l'objet.  À cette fin (et pour d'autres),
chaque objet contient également un pointeur vers son objet type.

La grande question demeure maintenant : quand utiliser "Py_INCREF(x)"
et "Py_DECREF(x)" ? Commençons par définir quelques termes. Personne
ne possède un objet, mais vous pouvez en *avoir une référence*. Le
compteur de références d'un objet est maintenant défini comme étant le
nombre de références à cet objet. Le propriétaire d'une référence est
responsable d'appeler "Py_DECREF()" lorsque la référence n'est plus
nécessaire. La possession d'une référence peut être transférée. Il y a
trois façons de se débarrasser d'une référence que l'on possède : la
transmettre, la stocker ou appeler "Py_DECREF()". Oublier de se
débarrasser d'une référence crée une fuite de mémoire.

It is also possible to *borrow* [1] a reference to an object.  The
borrower of a reference should not call "Py_DECREF()".  The borrower
must not hold on to the object longer than the owner from which it was
borrowed. Using a borrowed reference after the owner has disposed of
it risks using freed memory and should be avoided completely [2].

L'avantage d'emprunter, plutôt qu'être propriétaire d'une référence,
est que vous n'avez pas à vous soucier de libérer la référence sur
tous les chemins possibles dans le code — en d'autres termes, avec une
référence empruntée, vous ne courez pas le risque de fuites lors d'une
sortie prématurée. L'inconvénient de l'emprunt par rapport à la
possession est qu'il existe certaines situations subtiles où, dans un
code apparemment correct, une référence empruntée peut être utilisée
après que le propriétaire auquel elle a été empruntée l'a en fait
éliminée.

Une référence empruntée peut être changée en une référence possédée en
appelant "Py_INCREF()". Cela n'affecte pas le statut du propriétaire à
qui la référence a été empruntée — cela crée une nouvelle référence
possédée et donne l'entière responsabilité au propriétaire (le nouveau
propriétaire doit libérer la référence correctement, ainsi que le
propriétaire précédent).


Règles concernant la possession de références
---------------------------------------------

Chaque fois qu'une référence d'objet est passée à l'intérieur ou à
l'extérieur d'une fonction, elle fait partie de la spécification de
l'interface de la fonction, peu importe que la possession soit
transférée avec la référence ou non.

La plupart des fonctions qui renvoient une référence à un objet
transmettent la possession avec la référence. En particulier, toutes
les fonctions dont la fonction est de créer un nouvel objet, telles
que "PyLong_FromLong()" et "Py_BuildValue()", transmettent la
possession au récepteur. Même si l'objet n'est pas réellement nouveau,
vous recevez toujours la possession d'une nouvelle référence à cet
objet. Par exemple, "PyLong_FromLong()" maintient un cache des valeurs
souvent utilisées et peut renvoyer une référence à un élément mis en
cache.

De nombreuses fonctions qui extraient des objets d'autres objets
transfèrent également la possession avec la référence, par exemple
"PyObject_GetAttrString()". L'image est moins claire ici, cependant,
puisque quelques routines courantes sont des exceptions :
"PyTuple_GetItem()", "PyList_GetItem()", "PyDict_GetItem()" et
"PyDict_GetItemString()" renvoient toutes des références qui sont
empruntées au *n*-uplet, à la liste ou au dictionnaire.

La fonction "PyImport_AddModule()" renvoie également une référence
empruntée, même si elle peut en fait créer l'objet qu'elle renvoie :
c'est possible car une référence à l'objet est stockée dans
"sys.modules".

Lorsque vous passez une référence d'objet dans une autre fonction, en
général, la fonction vous emprunte la référence — si elle a besoin de
la stocker, elle utilise "Py_INCREF()" pour devenir un propriétaire
indépendant. Il existe exactement deux exceptions importantes à cette
règle : "PyTuple_SetItem()" et "PyList_SetItem()". Ces fonctions
s'approprient l'élément qui leur est transmis, même en cas d'échec !
(Notez que "PyDict_SetItem()" et compagnie ne prennent pas la
possession de l'objet, elles sont « normales ».)

Lorsqu'une fonction C est appelée depuis Python, elle emprunte à
l'appelant des références aux arguments. L'appelant possède une
référence à l'objet, de sorte que la durée de vie de la référence
empruntée est garantie jusqu'au retour de la fonction. Ce n'est que
lorsqu'une telle référence empruntée doit être stockée ou transmise
qu'elle doit être transformée en référence possédée en appelant
"Py_INCREF()".

La référence d'objet renvoyée par une fonction C appelée depuis Python
doit être une référence détenue en propre — la possession est
transférée de la fonction à son appelant.


Terrain dangereux
-----------------

Il existe quelques situations où l'utilisation apparemment inoffensive
d'une référence empruntée peut entraîner des problèmes. Tous ces
problèmes sont en lien avec des invocations implicites de
l’interpréteur et peuvent amener le propriétaire d'une référence à
s'en défaire.

Le premier cas, et le plus important à connaître, est celui de
l'utilisation de "Py_DECREF()" à un objet non relié lors de l'emprunt
d'une référence à un élément de liste. Par exemple :

   void
   bug(PyObject *list)
   {
       PyObject *item = PyList_GetItem(list, 0);

       PyList_SetItem(list, 1, PyLong_FromLong(0L));
       PyObject_Print(item, stdout, 0); /* BUG! */
   }

Cette fonction emprunte d'abord une référence à  "list[0]", puis
remplace  "list[1]" par la valeur  "0", et enfin affiche la référence
empruntée. Ça a l'air inoffensif, n'est-ce pas ? Mais ce n'est pas le
cas !

Let's follow the control flow into "PyList_SetItem()".  The list owns
references to all its items, so when item 1 is replaced, it has to
dispose of the original item 1.  Now let's suppose the original item 1
was an instance of a user-defined class, and let's further suppose
that the class defined a "__del__()" method.  If this class instance
has a reference count of 1, disposing of it will call its "__del__()"
method. Internally, "PyList_SetItem()" calls "Py_DECREF()" on the
replaced item, which invokes replaced item's corresponding
"tp_dealloc" function. During deallocation, "tp_dealloc" calls
"tp_finalize", which is mapped to the "__del__()" method for class
instances (see **PEP 442**). This entire sequence happens
synchronously within the "PyList_SetItem()" call.

Since it is written in Python, the "__del__()" method can execute
arbitrary Python code.  Could it perhaps do something to invalidate
the reference to "item" in "bug()"?  You bet!  Assuming that the list
passed into "bug()" is accessible to the "__del__()" method, it could
execute a statement to the effect of "del list[0]", and assuming this
was the last reference to that object, it would free the memory
associated with it, thereby invalidating "item".

La solution, une fois que vous connaissez la source du problème, est
simple : incrémentez temporairement le compteur de références. La
version correcte de la fonction est :

   void
   no_bug(PyObject *list)
   {
       PyObject *item = PyList_GetItem(list, 0);

       Py_INCREF(item);
       PyList_SetItem(list, 1, PyLong_FromLong(0L));
       PyObject_Print(item, stdout, 0);
       Py_DECREF(item);
   }

This is a true story.  An older version of Python contained variants
of this bug and someone spent a considerable amount of time in a C
debugger to figure out why his "__del__()" methods would fail...

The second case of problems with a borrowed reference is a variant
involving threads.  Normally, multiple threads in the Python
interpreter can't get in each other's way, because there is a *global
lock* protecting Python's entire object space. However, it is possible
to temporarily release this lock using the macro
"Py_BEGIN_ALLOW_THREADS", and to re-acquire it using
"Py_END_ALLOW_THREADS".  This is common around blocking I/O calls, to
let other threads use the processor while waiting for the I/O to
complete. Obviously, the following function has the same problem as
the previous one:

   void
   bug(PyObject *list)
   {
       PyObject *item = PyList_GetItem(list, 0);
       Py_BEGIN_ALLOW_THREADS
       ...some blocking I/O call...
       Py_END_ALLOW_THREADS
       PyObject_Print(item, stdout, 0); /* BUG! */
   }


Pointeurs "NULL"
----------------

En général, les fonctions qui prennent des références d'objets comme
arguments ne sont pas conçues pour recevoir des pointeurs "NULL", et
si vous en donnez comme arguments, elles causeront une erreur de
segmentation (ou provoqueront des *core dump* ultérieurs). Les
fonctions qui renvoient des références d'objets renvoient généralement
"NULL" uniquement pour indiquer qu'une exception s'est produite.  La
raison pour laquelle les arguments "NULL" ne sont pas testés est que
les fonctions passent souvent les objets qu'elles reçoivent à d'autres
fonctions, si chaque fonction devait tester pour "NULL", il y aurait
beaucoup de tests redondants et le code s'exécuterait plus lentement.

Il est préférable de tester la présence de "NULL" uniquement au début
: lorsqu'un pointeur qui peut être "NULL" est reçu, par exemple, de
"malloc()" ou d'une fonction qui peut lever une exception.

Les macros "Py_INCREF()" et "Py_DECREF()" ne vérifient pas les
pointeurs "NULL". Cependant, leurs variantes "Py_XINCREF()" et
"Py_XDECREF()" le font.

Les macros de vérification d'un type d'objet particulier
("Pytype_Check()") ne vérifient pas les pointeurs "NULL" — encore une
fois, il y a beaucoup de code qui en appelle plusieurs à la suite pour
tester un objet par rapport à différents types attendus, ce qui
générerait des tests redondants. Il n'y a pas de variantes avec la
vérification "NULL".

The C function calling mechanism guarantees that the argument list
passed to C functions ("args" in the examples) is never "NULL" --- in
fact it guarantees that it is always a tuple [3].

C'est une grave erreur de laisser un pointeur "NULL" « s'échapper »
vers l'utilisateur Python.


Écrire des extensions en C++
============================

C'est possible d'écrire des modules d'extension en C++, mais sous
certaines conditions. Si le programme principal (l'interpréteur
Python) est compilé et lié par le compilateur C, les objets globaux ou
statiques avec les constructeurs ne peuvent pas être utilisés. Ceci
n'est pas un problème si le programme principal est relié par le
compilateur C++. Les fonctions qui seront appelées par l'interpréteur
Python (en particulier, les fonctions d'initialisation des modules)
doivent être déclarées en utilisant "extern "C"". Il n'est pas
nécessaire d'inclure les fichiers d'en-tête Python dans le "extern "C"
{…}", car ils utilisent déjà ce format si le symbole "__cplusplus" est
défini (tous les compilateurs C++ récents définissent ce symbole).


Fournir une API en langage C pour un module d'extension
=======================================================

De nombreux modules d'extension fournissent simplement de nouvelles
fonctions et de nouveaux types à utiliser à partir de Python, mais
parfois le code d'un module d'extension peut être utile pour d'autres
modules d'extension. Par exemple, un module d'extension peut mettre en
œuvre un type « collection » qui fonctionne comme des listes sans
ordre. Tout comme le type de liste Python standard possède une API C
qui permet aux modules d'extension de créer et de manipuler des
listes, ce nouveau type de collection devrait posséder un ensemble de
fonctions C pour une manipulation directe à partir d'autres modules
d'extension.

À première vue, cela semble facile : il suffit d'écrire les fonctions
(sans les déclarer « statiques », bien sûr), de fournir un fichier d
'en-tête approprié et de documenter l'API C. Et en fait, cela
fonctionnerait si tous les modules d'extension étaient toujours liés
statiquement avec l'interpréteur Python. Cependant, lorsque les
modules sont utilisés comme des bibliothèques partagées, les symboles
définis dans un module peuvent ne pas être visibles par un autre
module. Les détails de la visibilité dépendent du système
d'exploitation ; certains systèmes utilisent un espace de noms global
pour l'interpréteur Python et tous les modules d'extension (Windows,
par exemple), tandis que d'autres exigent une liste explicite des
symboles importés au moment de la liaison des modules (AIX en est un
exemple), ou offrent un choix de stratégies différentes (la plupart
des *Unix*). Et même si les symboles sont globalement visibles, le
module dont on souhaite appeler les fonctions n'est peut-être pas
encore chargé !

Portability therefore requires not to make any assumptions about
symbol visibility. This means that all symbols in extension modules
should be declared "static", except for the module's initialization
function, in order to avoid name clashes with other extension modules.
And it means that symbols that *should* be accessible from other
extension modules must be exported in a different way.

Python fournit un mécanisme spécial pour transmettre des informations
de niveau C (pointeurs) d'un module d'extension à un autre : les
Capsules. Une capsule est un type de données Python qui stocke un
pointeur (void*). Les capsules ne peuvent être créées et accessibles
que via leur API C, mais elles peuvent être transmises comme n'importe
quel autre objet Python. En particulier, elles peuvent être affectées
à un nom dans l'espace de noms d'un module d'extension. D'autres
modules d'extension peuvent alors importer ce module, récupérer la
valeur de ce nom, puis récupérer le pointeur de la Capsule.

Il existe de nombreuses façons d'utiliser les Capsules pour exporter
l'API C d'un module d'extension. Chaque fonction peut obtenir sa
propre Capsule, ou tous les pointeurs de l'API C peuvent être stockés
dans un tableau dont l'adresse est inscrite dans une Capsule. Et les
différentes tâches de stockage et de récupération des pointeurs
peuvent être réparties de différentes manières entre le module
fournissant le code et les modules clients.

Quelle que soit la méthode que vous choisissez, il est important de
bien nommer vos Capsules. La fonction "PyCapsule_New()" prend un
paramètre nommé (const char*). Vous êtes autorisé à passer un nom
"NULL", mais nous vous encourageons vivement à spécifier un nom. Des
Capsules correctement nommées offrent un certain degré de sécurité
concernant un éventuel conflit de types, car il n'y a pas de moyen de
distinguer deux ou plusieurs Capsules non nommées entre elles.

En particulier, les capsules utilisées pour exposer les API C doivent
recevoir un nom suivant cette convention :

   modulename.attributename

La fonction de commodité "PyCapsule_Import()" permet de charger
facilement une API C fournie via une Capsule, mais seulement si le nom
de la Capsule correspond à cette convention. Ce comportement donne aux
utilisateurs d'API C un degré élevé de certitude que la Capsule qu'ils
chargent contient l'API C correcte.

L'exemple suivant montre une approche qui fait peser la plus grande
partie de la charge sur le rédacteur du module d'exportation, ce qui
est approprié pour les modules de bibliothèque couramment utilisés. Il
stocke tous les pointeurs de l'API C (un seul dans l'exemple !) dans
un tableau de pointeurs void qui devient la valeur d'une Capsule. Le
fichier d'en-tête correspondant au module fournit une macro qui se
charge d'importer le module et de récupérer ses pointeurs d'API C. Les
modules clients n'ont qu'à appeler cette macro avant d'accéder à l'API
C.

The exporting module is a modification of the "spam" module from the
tutorial. The function "spam.system()" does not call the C library
function "system()" directly, but a function "PySpam_System()", which
would of course do something more complicated in reality (such as
adding "spam" to every command). This function "PySpam_System()" is
also exported to other extension modules.

The function "PySpam_System()" is a plain C function, declared
"static" like everything else:

   static int
   PySpam_System(const char *command)
   {
       return system(command);
   }

The function "spam_system()" is modified in a trivial way:

   static PyObject *
   spam_system(PyObject *self, PyObject *args)
   {
       const char *command;
       int sts;

       if (!PyArg_ParseTuple(args, "s", &command))
           return NULL;
       sts = PySpam_System(command);
       return PyLong_FromLong(sts);
   }

Au début du module, immédiatement après la ligne :

   #include <Python.h>

on doit ajouter deux lignes supplémentaires :

   #define SPAM_MODULE
   #include "spammodule.h"

The "#define" is used to tell the header file that it is being
included in the exporting module, not a client module. Finally, the
module's "mod_exec" function must take care of initializing the C API
pointer array:

   static int
   spam_module_exec(PyObject *m)
   {
       static void *PySpam_API[PySpam_API_pointers];
       PyObject *c_api_object;

       /* Initialize the C API pointer array */
       PySpam_API[PySpam_System_NUM] = (void *)PySpam_System;

       /* Create a Capsule containing the API pointer array's address */
       c_api_object = PyCapsule_New((void *)PySpam_API, "spam._C_API", NULL);

       if (PyModule_Add(m, "_C_API", c_api_object) < 0) {
           return -1;
       }

       return 0;
   }

Note that "PySpam_API" is declared "static"; otherwise the pointer
array would disappear when "PyInit_spam()" terminates!

L'essentiel du travail se trouve dans le fichier d'en-tête
"spammodule.h", qui ressemble à ceci :

   #ifndef Py_SPAMMODULE_H
   #define Py_SPAMMODULE_H
   #ifdef __cplusplus
   extern "C" {
   #endif

   /* Header file for spammodule */

   /* C API functions */
   #define PySpam_System_NUM 0
   #define PySpam_System_RETURN int
   #define PySpam_System_PROTO (const char *command)

   /* Total number of C API pointers */
   #define PySpam_API_pointers 1


   #ifdef SPAM_MODULE
   /* This section is used when compiling spammodule.c */

   static PySpam_System_RETURN PySpam_System PySpam_System_PROTO;

   #else
   /* This section is used in modules that use spammodule's API */

   static void **PySpam_API;

   #define PySpam_System \
    (*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])

   /* Return -1 on error, 0 on success.
    * PyCapsule_Import will set an exception if there's an error.
    */
   static int
   import_spam(void)
   {
       PySpam_API = (void **)PyCapsule_Import("spam._C_API", 0);
       return (PySpam_API != NULL) ? 0 : -1;
   }

   #endif

   #ifdef __cplusplus
   }
   #endif

   #endif /* !defined(Py_SPAMMODULE_H) */

All that a client module must do in order to have access to the
function "PySpam_System()" is to call the function (or rather macro)
"import_spam()" in its "mod_exec" function:

   static int
   client_module_exec(PyObject *m)
   {
       if (import_spam() < 0) {
           return -1;
       }
       /* additional initialization can happen here */
       return 0;
   }

Le principal inconvénient de cette approche est que le fichier
"spammodule.h" est assez compliqué. Cependant, la structure de base
est la même pour chaque fonction exportée, ce qui fait qu'elle ne doit
être apprise qu'une seule fois.

Enfin, il convient de mentionner que les Capsules offrent des
fonctionnalités supplémentaires, qui sont particulièrement utiles pour
l'allocation de la mémoire et la dés-allocation du pointeur stocké
dans un objet Capsule. Les détails sont décrits dans le manuel de
référence de l'API Python/C dans la section Capsules et dans
l'implémentation des Capsules (fichiers "Include/pycapsule.h" et
"Objects/pycapsule.c" dans la distribution du code source Python).

-[ Notes ]-

[1] L'expression « emprunter une référence » n'est pas tout à fait
    correcte, car le propriétaire a toujours une copie de la
    référence.

[2] Vérifier que le comptage de référence est d'au moins 1 **ne
    fonctionne pas**, le compte de référence lui-même pourrait être en
    mémoire libérée et peut donc être réutilisé pour un autre objet !

[3] Ces garanties ne sont pas valables lorsqu'on emploie les
    conventions de nommage anciennes, qu'on retrouve encore assez
    souvent dans beaucoup de code existant.
