1. Étendre Python en C ou C++
*****************************

Il est relativement facile d'ajouter de nouveaux modules à Python, si
vous savez programmer en C. Ces *modules d'extension* permettent deux
choses qui ne sont pas possibles directement en Python : ils peuvent
définir de nouveaux types natifs et peuvent appeler des fonctions de
bibliothèques C ou faire des appels systèmes.

Pour gérer les extensions, l'API Python (*Application Programmer
Interface*) définit un ensemble de fonctions, macros et variables qui
donnent accès à la plupart des aspects du système d'exécution de
Python. L'API Python est incorporée dans un fichier source C en
incluant l'en-tête "Python.h".

La compilation d'un module d'extension dépend de l'usage prévu et de
la configuration du système, plus de détails peuvent être trouvés dans
les chapitres suivants.

Note:

  l'interface d'extension C est spécifique à *CPython*, et les modules
  d'extension ne fonctionnent pas sur les autres implémentations de
  Python. Dans de nombreux cas, il est possible d'éviter la rédaction
  des extensions en C et ainsi préserver la portabilité vers d'autres
  implémentations. Par exemple, si vous devez appeler une fonction de
  la bibliothèque C ou faire un appel système, vous devriez envisager
  d'utiliser le module "ctypes" ou d'utiliser la bibliothèque cffi
  plutôt que d'écrire du code C sur mesure. Ces modules vous
  permettent d'écrire du code Python s'interfaçant avec le code C et
  sont plus portables entre les implémentations de Python que
  l'écriture et la compilation d'une d'extension C.


1.1. Un exemple simple
======================

Créons un module d'extension appelé "spam" (la nourriture préférée de
fans des *Monty Python*) et disons que nous voulons créer une
interface Python à la fonction de la bibliothèque C "system()" [1].
Cette fonction prend une chaîne de caractères à terminaison nulle
comme argument et renvoie un entier. Nous voulons que cette fonction
soit appelable à partir de Python comme suit :

   >>> import spam
   >>> status = spam.system("ls -l")

Commençons par créer un fichier "spammodule.c" (historiquement, si un
module se nomme "spam", le fichier C contenant son implémentation est
appelé "spammodule.c" ; si le nom du module est très long, comme
"spammify", le nom du module peut être juste "spammify.c").

Les deux premières lignes de notre fichier peuvent être :

   #define PY_SSIZE_T_CLEAN
   #include <Python.h>

qui récupère l'API Python (vous pouvez ajouter un commentaire
décrivant le but du module et un avis de droit d'auteur si vous le
souhaitez).

Note:

  il est possible que Python déclare certaines définitions
  pré-processeur qui affectent les têtes standards sur certains
  systèmes, vous *devez* donc inclure "Python.h" avant les en-têtes
  standards."#define PY_SSIZE_T_CLEAN" was used to indicate that
  "Py_ssize_t" should be used in some APIs instead of "int". It is not
  necessary since Python 3.13, but we keep it here for backward
  compatibility. See Chaînes et tampons for a description of this
  macro.

All user-visible symbols defined by "Python.h" have a prefix of "Py"
or "PY", except those defined in standard header files.

Astuce:

  For backward compatibility, "Python.h" includes several standard
  header files. C extensions should include the standard headers that
  they use, and should not rely on these implicit includes. If using
  the limited C API version 3.13 or newer, the implicit includes are:

  * "<assert.h>"

  * "<intrin.h>" (on Windows)

  * "<inttypes.h>"

  * "<limits.h>"

  * "<math.h>"

  * "<stdarg.h>"

  * "<wchar.h>"

  * "<sys/types.h>" (if present)

  If "Py_LIMITED_API" is not defined, or is set to version 3.12 or
  older, the headers below are also included:

  * "<ctype.h>"

  * "<unistd.h>" (on POSIX)

  If "Py_LIMITED_API" is not defined, or is set to version 3.10 or
  older, the headers below are also included:

  * "<errno.h>"

  * "<stdio.h>"

  * "<stdlib.h>"

  * "<string.h>"

La prochaine chose que nous ajoutons à notre fichier de module est la
fonction C qui sera appelée lorsque l'expression Python
"spam.system(chaîne)" sera évaluée (nous verrons bientôt comment elle
finit par être appelée) :

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

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

Il y a une correspondance directe de la liste des arguments en Python
(par exemple, l'expression ""ls -l"") aux arguments passés à la
fonction C. La fonction C a toujours deux arguments, appelés par
convention *self* et *args*.

Pour les fonctions au niveau du module, l'argument *self* pointe sur
l'objet module, pour une méthode, il pointe sur l'instance de l'objet.

L'argument *args* sera un pointeur vers un *n*-uplet Python contenant
les arguments. Chaque élément du *n*-uplet correspond à un argument
dans la liste des arguments de l'appel. Les arguments sont des objets
Python, afin d'en faire quelque chose dans notre fonction C, nous
devons les convertir en valeurs C. La fonction "PyArg_ParseTuple()" de
l'API Python vérifie les types des arguments et les convertit en
valeurs C. Elle utilise un modèle sous forme de chaîne pour déterminer
les types requis des arguments ainsi que les types de variables C dans
lequel stocker les valeurs converties. Nous approfondirons ceci plus
tard.

"PyArg_ParseTuple()" renvoie vrai (pas zéro) si tous les arguments ont
le bon type et que ses composants ont été stockés dans les variables
dont les adresses ont été données en entrée. Elle renvoie faux (zéro)
si une liste d'arguments invalide a été passée. Dans ce dernier cas,
elle lève également une exception appropriée de sorte que la fonction
d'appel puisse renvoyer "NULL" immédiatement (comme nous l'avons vu
dans l'exemple).


1.2. Intermezzo : les erreurs et les 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);
   }


1.3. Retour vers l'exemple
==========================

En revenant vers notre fonction exemple, vous devriez maintenant être
capable de comprendre cette affirmation :

   if (!PyArg_ParseTuple(args, "s", &command))
       return NULL;

Elle renvoie "NULL" (l'indicateur d'erreur pour les fonctions
renvoyant des pointeurs d'objet) si une erreur est détectée dans la
liste des arguments, se fiant à l'exception définie par
"PyArg_ParseTuple()". Autrement, la valeur chaîne de l'argument a été
copiée dans la variable locale "command". Il s'agit d'une attribution
de pointeur et vous n'êtes pas supposés modifier la chaîne vers
laquelle il pointe (donc en C Standard, la variable "command" doit
être clairement déclarée comme "const char *command").

La prochaine instruction est un appel à la fonction Unix "system()",
en lui passant la chaîne que nous venons d'obtenir à partir de
"PyArg_ParseTuple()" :

   sts = system(command);

Notre fonction "spam.system()" doit renvoyer la valeur de "sts" comme
un objet Python. Cela est effectué par l'utilisation de la fonction
"PyLong_FromLong()".

   return PyLong_FromLong(sts);

Dans ce cas, elle renvoie un objet de type entier (oui, même les
entiers sont des objets, stockés dans le tas, en Python !).

Si vous avez une fonction C qui ne renvoie aucun argument utile (une
fonction renvoyant void), la fonction Python correspondante doit
renvoyer "None". Vous aurez besoin de cet idiome pour cela (qui est
implémenté par la macro "Py_RETURN_NONE") :

   Py_INCREF(Py_None);
   return Py_None;

"Py_None" est la dénomination en C pour l'objet spécial Python "None".
C'est un authentique objet Python plutôt qu'un pointeur "NULL" qui,
dans la plupart des situations, signifie qu'une erreur est survenue
comme nous l'avons vu.


1.4. La fonction d'initialisation et le tableau des méthodes du module
======================================================================

I promised to show how "spam_system()" is called from Python programs.
First, we need to list its name and address in a "method table":

   static PyMethodDef spam_methods[] = {
       ...
       {"system",  spam_system, METH_VARARGS,
        "Execute a shell command."},
       ...
       {NULL, NULL, 0, NULL}        /* Sentinel */
   };

Notez la troisième entrée ("METH_VARARGS"). C'est un indicateur du
type de convention à utiliser pour la fonction C, à destination de
l'interpréteur. Il doit valoir normalement "METH_VARARGS" ou
"METH_VARARGS | METH_KEYWORDS" ; la valeur "0" indique qu'une variante
obsolète de "PyArg_ParseTuple()" est utilisée.

Si seulement "METH_VARARGS" est utilisé, la fonction s'attend à ce que
les paramètres Python soient passés comme un *n*-uplet que l'on peut
analyser *via* "PyArg_ParseTuple()" ; des informations supplémentaires
sont fournies plus bas.

Le bit "METH_KEYWORDS" peut être mis à un dans le troisième champ si
des arguments par mots-clés doivent être passés à la fonction. Dans ce
cas, la fonction C doit accepter un troisième paramètre "PyObject *"
qui est un dictionnaire des mots-clés. Utilisez
"PyArg_ParseTupleAndKeywords()" pour analyser les arguments d'une
telle fonction.

Le tableau des méthodes doit être référencé dans la structure de
définition du module :

   static struct PyModuleDef spam_module = {
       ...
       .m_methods = spam_methods,
       ...
   };

This structure, in turn, must be passed to the interpreter in the
module's initialization function.  The initialization function must be
named "PyInit_name()", where *name* is the name of the module, and
should be the only non-"static" item defined in the module file:

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

Note that "PyMODINIT_FUNC" declares the function as "PyObject *"
return type, declares any special linkage declarations required by the
platform, and for C++ declares the function as "extern "C"".

"PyInit_spam()" is called when each interpreter imports its module
"spam" for the first time.  (See below for comments about embedding
Python.) A pointer to the module definition must be returned via
"PyModuleDef_Init()", so that the import machinery can create the
module and store it in "sys.modules".

When embedding Python, the "PyInit_spam()" function is not called
automatically unless there's an entry in the "PyImport_Inittab" table.
To add the module to the initialization table, use
"PyImport_AppendInittab()", optionally followed by an import of the
module:

   #define PY_SSIZE_T_CLEAN
   #include <Python.h>

   int
   main(int argc, char *argv[])
   {
       PyStatus status;
       PyConfig config;
       PyConfig_InitPythonConfig(&config);

       /* Add a built-in module, before Py_Initialize */
       if (PyImport_AppendInittab("spam", PyInit_spam) == -1) {
           fprintf(stderr, "Error: could not extend in-built modules table\n");
           exit(1);
       }

       /* Pass argv[0] to the Python interpreter */
       status = PyConfig_SetBytesString(&config, &config.program_name, argv[0]);
       if (PyStatus_Exception(status)) {
           goto exception;
       }

       /* Initialize the Python interpreter.  Required.
          If this step fails, it will be a fatal error. */
       status = Py_InitializeFromConfig(&config);
       if (PyStatus_Exception(status)) {
           goto exception;
       }
       PyConfig_Clear(&config);

       /* Optionally import the module; alternatively,
          import can be deferred until the embedded script
          imports it. */
       PyObject *pmodule = PyImport_ImportModule("spam");
       if (!pmodule) {
           PyErr_Print();
           fprintf(stderr, "Error: could not import module 'spam'\n");
       }

       // ... use Python C API here ...

       return 0;

     exception:
        PyConfig_Clear(&config);
        Py_ExitStatusException(status);
   }

Note:

  If you declare a global variable or a local static one, the module
  may experience unintended side-effects on re-initialisation, for
  example when removing entries from "sys.modules" or importing
  compiled modules into multiple interpreters within a process (or
  following a "fork()" without an intervening "exec()"). If module
  state is not yet fully isolated, authors should consider marking the
  module as having no support for subinterpreters (via
  "Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED").

A more substantial example module is included in the Python source
distribution as "Modules/xxlimited.c".  This file may be used as a
template or simply read as an example.


1.5. Compilation et liaison
===========================

Il y a encore deux choses à faire avant de pouvoir utiliser votre
nouvelle extension : la compiler et la lier au système Python. Si vous
utilisez le chargement dynamique, les détails peuvent dépendre du
style de chargement dynamique utilisé par votre système ; voir les
chapitres sur la compilation de modules d'extension (chapitre
Construire des extensions C et C++) et les informations
supplémentaires concernant uniquement la construction sous Windows
(chapitre Construire des extensions C et C++ sur Windows) pour plus
d'informations à ce sujet.

Si vous ne pouvez pas utiliser le chargement dynamique, ou si vous
voulez faire de votre module une partie permanente de l'interpréteur
Python, vous devez modifier la configuration et reconstruire
l'interpréteur. Heureusement, c'est très simple sous Unix : placez
simplement votre fichier ("spammodule.c" par exemple) dans le
répertoire "Modules/" d'une distribution source décompressée, ajoutez
une ligne au fichier "Modules/Setup.local" décrivant votre fichier :

   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


1.6. Appeler des fonctions Python en C
======================================

Jusqu'à présent, nous nous sommes concentrés sur le fait de rendre les
fonctions C appelables depuis Python. L'inverse est également utile :
appeler des fonctions Python depuis C. C'est notamment le cas pour les
bibliothèques qui gèrent les fonctions dites de « rappel » (*callback*
en anglais). Si une interface C utilise des rappels, l'équivalent
Python doit souvent fournir un mécanisme de rappel au développeur
Python ; l'implémentation nécessite d'appeler les fonctions de rappel
Python à partir d'un rappel C. D'autres utilisations sont également
envisageables.

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;
   }

Cette fonction doit être déclarée en utilisant le drapeau
"METH_VARARGS" ; ceci est décrit dans la section La fonction
d'initialisation et le tableau des méthodes du module.  La fonction
"PyArg_ParseTuple()" et ses arguments sont documentés dans la 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);


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

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

   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.

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 :

   #define PY_SSIZE_T_CLEAN
   #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) */
   }


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

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 */
   };

   static struct PyModuleDef keywdarg_module = {
       .m_base = PyModuleDef_HEAD_INIT,
       .m_name = "keywdarg",
       .m_size = 0,
       .m_methods = keywdarg_methods,
   };

   PyMODINIT_FUNC
   PyInit_keywdarg(void)
   {
       return PyModuleDef_Init(&keywdarg_module);
   }


1.9. 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))


1.10. 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.


1.10.1. 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.

Il est également possible d'*emprunter* [2] une référence à un objet.
L'emprunteur d'une référence ne doit pas appeler "Py_DECREF()".
L'emprunteur ne doit pas conserver l'objet plus longtemps que le
propriétaire à qui il a été emprunté. L'utilisation d'une référence
empruntée après que le propriétaire s'en est débarrassée risque
d'utiliser de la mémoire libérée et doit être absolument évitée [3].

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).


1.10.2. 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.


1.10.3. 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! */
   }


1.10.4. 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".

Le mécanisme d'appel de fonctions C garantit que la liste d'arguments
passée aux fonctions C ("args" dans les exemples) n'est jamais "NULL".
En fait, il garantit qu'il s'agit toujours d'un *n*-uplet [4].

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


1.11. É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).


1.12. 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é !

La portabilité exige donc de ne faire aucune supposition sur la
visibilité des symboles. Cela signifie que tous les symboles des
modules d'extension doivent être déclarés "static", à l'exception de
la fonction d'initialisation du module, afin d'éviter les conflits de
noms avec les autres modules d'extension (comme discuté dans la
section La fonction d'initialisation et le tableau des méthodes du
module). Et cela signifie que les symboles qui *devraient* être
accessibles à partir d'autres modules d'extension doivent être
exportés d'une manière différente.

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
section Un exemple simple. 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] Une interface pour cette fonction existe déjà dans le module
    standard "os", elle a été choisie comme un exemple simple et
    direct.

[2] 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.

[3] 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 !

[4] 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.
