1. Extendiendo Python con C o C++
*********************************

Es muy fácil agregar nuevos módulos incorporados a Python, si sabe
cómo programar en C. Tales como *módulos de extensión* pueden hacer
dos cosas que no se pueden hacer directamente en Python: pueden
implementar nuevos tipos objetos incorporados, y pueden llamar a
funciones de biblioteca C y llamadas de sistema.

Para admitir extensiones, la API de Python (interfaz de programadores
de aplicaciones) define un conjunto de funciones, macros y variables
que proporcionan acceso a la mayoría de los aspectos del sistema de
tiempo de ejecución de Python. La API de Python se incorpora en un
archivo fuente C incluyendo el encabezado ""Python.h"".

La compilación de un módulo de extensión depende de su uso previsto,
así como de la configuración de su sistema; los detalles se dan en
capítulos posteriores.

Nota:

  La interfaz de extensión C es específica de CPython, y los módulos
  de extensión no funcionan en otras implementaciones de Python. En
  muchos casos, es posible evitar escribir extensiones C y preservar
  la portabilidad a otras implementaciones. Por ejemplo, si su caso de
  uso es llamar a funciones de biblioteca C o llamadas de sistema,
  debería considerar usar el módulo "ctypes" o la biblioteca cffi en
  lugar de escribir código personalizado C. Estos módulos le permiten
  escribir código Python para interactuar con el código C y son más
  portátiles entre las implementaciones de Python que escribir y
  compilar un módulo de extensión C.


1.1. Un ejemplo simple
======================

Creemos un módulo de extensión llamado "spam" (la comida favorita de
los fanáticos de Monty Python ...) y digamos que queremos crear una
interfaz de Python para la función de biblioteca C "system()" [1] .
Esta función toma una cadena de caracteres con terminación nula como
argumento y retorna un entero. Queremos que esta función se pueda
llamar desde Python de la siguiente manera:

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

Comience creando un archivo "spammodule.c". (Históricamente, si un
módulo se llama "spam", el archivo C que contiene su implementación se
llama "spammodule.c"; si el nombre del módulo es muy largo, como
"spammify", el nombre del módulo puede sea solo "spammify.c".)

Las dos primeras líneas de nuestro archivo pueden ser:

   #define PY_SSIZE_T_CLEAN
   #include <Python.h>

que extrae la API de Python (puede agregar un comentario que describa
el propósito del módulo y un aviso de copyright si lo desea).

Nota:

  Dado que Python puede definir algunas definiciones de preprocesador
  que afectan los encabezados estándar en algunos sistemas, *debe*
  incluir "Python.h" antes de incluir encabezados estándar.Se
  recomienda definir siempre "PY_SSIZE_T_CLEAN" antes de incluir
  "Python.h". Consulte Extracción de parámetros en funciones de
  extensión para obtener una descripción de esta macro.

Todos los símbolos visibles para el usuario definidos por "Python.h"
tienen un prefijo "Py" o "PY", excepto los definidos en los archivos
de encabezado estándar. Por conveniencia, y dado que el intérprete de
Python los usa ampliamente, ""Python.h"" incluye algunos archivos de
encabezado estándar: "<stdio.h>", "<string.h>", "<errno.h>", y
"<stdlib.h>". Si el último archivo de encabezado no existe en su
sistema, declara las funciones "malloc()", "free()" y "realloc()"
directamente.

Lo siguiente que agregamos a nuestro archivo de módulo es la función C
que se llamará cuando se evalúe la expresión Python
"spam.system(string)" (veremos en breve cómo termina siendo llamado):

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

Hay una traducción directa de la lista de argumentos en Python (por
ejemplo, la única expresión ""ls -l"") a los argumentos pasados a la
función C. La función C siempre tiene dos argumentos, llamados
convencionalmente *self* y *args*.

El argumento *self* apunta al objeto del módulo para funciones a nivel
de módulo; para un método apuntaría a la instancia del objeto.

El argumento *args* será un puntero a un objeto de tupla de Python que
contiene los argumentos. Cada elemento de la tupla corresponde a un
argumento en la lista de argumentos de la llamada. Los argumentos son
objetos de Python --- para hacer algo con ellos en nuestra función C
tenemos que convertirlos a valores C. La función "PyArg_ParseTuple()"
en la API de Python verifica los tipos de argumento y los convierte a
valores C. Utiliza una cadena de plantilla para determinar los tipos
requeridos de los argumentos, así como los tipos de las variables C en
las que almacenar los valores convertidos. Más sobre esto más tarde.

"PyArg_ParseTuple()" retorna verdadero (distinto de cero) si todos los
argumentos tienen el tipo correcto y sus componentes se han almacenado
en las variables cuyas direcciones se pasan. Retorna falso (cero) si
se pasó una lista de argumentos no válidos. En el último caso, también
genera una excepción apropiada para que la función de llamada pueda
retornar "NULL" inmediatamente (como vimos en el ejemplo).


1.2. Intermezzo: errores y excepciones
======================================

An important convention throughout the Python interpreter is the
following: when a function fails, it should set an exception condition
and return an error value (usually "-1" or a "NULL" pointer).
Exception information is stored in three members of the interpreter's
thread state.  These are "NULL" if there is no exception.  Otherwise
they are the C equivalents of the members of the Python tuple returned
by "sys.exc_info()".  These are the exception type, exception
instance, and a traceback object.  It is important to know about them
to understand how errors are passed around.

La API de Python define una serie de funciones para establecer varios
tipos de excepciones.

El más común es "PyErr_SetString()". Sus argumentos son un objeto de
excepción y una cadena C. El objeto de excepción suele ser un objeto
predefinido como "PyExc_ZeroDivisionError". La cadena C indica la
causa del error y se convierte en un objeto de cadena Python y se
almacena como el "valor asociado" de la excepción.

Otra función útil es "PyErr_SetFromErrno()", que solo toma un
argumento de excepción y construye el valor asociado mediante la
inspección de la variable global "errno". La función más general es
"PyErr_SetObject()", que toma dos argumentos de objeto, la excepción y
su valor asociado. No necesita "Py_INCREF()" los objetos pasados a
cualquiera de estas funciones.

Puede probar de forma no destructiva si se ha establecido una
excepción con "PyErr_Occurred()". Esto retorna el objeto de excepción
actual o "NULL" si no se ha producido ninguna excepción. Normalmente
no necesita llamar a "PyErr_Occurred()" para ver si se produjo un
error en una llamada a la función, ya que debería poder distinguir el
valor de retorno.

Cuando una función *f* que llama a otra función *g* detecta que la
última falla, *f* debería retornar un valor de error (generalmente
"NULL" o "-1"). Debería *no* llamar a una de las funciones "PyErr_*()"
--- una ya ha sido llamada por *g*. Se supone que la persona que llama
*f* también debe retornar una indicación de error a *su* persona que
llama, de nuevo *sin* llamar "PyErr_*()", y así sucesivamente --- la
causa más detallada del error ya fue informado por la función que lo
detectó por primera vez. Una vez que el error llega al bucle principal
del intérprete de Python, esto anula el código de Python que se está
ejecutando actualmente e intenta encontrar un controlador de excepción
especificado por el programador de Python.

(Hay situaciones en las que un módulo puede dar un mensaje de error
más detallado llamando a otra función "PyErr_*()", y en tales casos
está bien hacerlo. Como regla general, sin embargo, esto es no es
necesario y puede causar que se pierda información sobre la causa del
error: la mayoría de las operaciones pueden fallar por varias
razones.)

Para ignorar una excepción establecida por una llamada de función que
falló, la condición de excepción debe borrarse explícitamente llamando
a "PyErr_Clear()". La única vez que el código C debe llamar
"PyErr_Clear()" es si no quiere pasar el error al intérprete pero
quiere manejarlo completamente por sí mismo (posiblemente probando
algo más o pretendiendo que nada salió mal) )

Cada llamada fallida a "malloc()" debe convertirse en una excepción
--- la persona que llama directamente de "malloc()" (o "realloc()")
debe llamar "PyErr_NoMemory()" y retorna un indicador de falla en sí
mismo. Todas las funciones de creación de objetos (por ejemplo,
"PyLong_FromLong()") ya hacen esto, por lo que esta nota solo es
relevante para aquellos que llaman "malloc()" directamente.

También tenga en cuenta que, con la importante excepción de
"PyArg_ParseTuple()" y sus amigos, las funciones que retornan un
estado entero generalmente retornan un valor positivo o cero para el
éxito y "-1" para el fracaso, como las llamadas al sistema Unix.

Finalmente, tenga cuidado de limpiar la basura (haciendo
"Py_XDECREF()" o "Py_DECREF()" requiere objetos que ya ha creado)
cuando retorna un indicador de error!

La elección de qué excepción lanzar es totalmente suya. Hay objetos C
declarados previamente que corresponden a todas las excepciones de
Python incorporadas, como "PyExc_ZeroDivisionError", que puede usar
directamente. Por supuesto, debe elegir sabiamente las excepciones ---
no use "PyExc_TypeError" para significar que no se puede abrir un
archivo (probablemente debería ser "PyExc_IOError"). Si algo anda mal
con la lista de argumentos, la función "PyArg_ParseTuple()"
generalmente genera "PyExc_TypeError". Si tiene un argumento cuyo
valor debe estar en un rango particular o debe satisfacer otras
condiciones, "PyExc_ValueError" es apropiado.

También puede definir una nueva excepción que sea exclusiva de su
módulo. Para esto, generalmente declara una variable de objeto
estático al comienzo de su archivo:

   static PyObject *SpamError;

y lo inicializa en la función de inicialización de su módulo
("PyInit_spam()") con un objeto de excepción:

   PyMODINIT_FUNC
   PyInit_spam(void)
   {
       PyObject *m;

       m = PyModule_Create(&spammodule);
       if (m == NULL)
           return NULL;

       SpamError = PyErr_NewException("spam.error", NULL, NULL);
       Py_XINCREF(SpamError);
       if (PyModule_AddObject(m, "error", SpamError) < 0) {
           Py_XDECREF(SpamError);
           Py_CLEAR(SpamError);
           Py_DECREF(m);
           return NULL;
       }

       return m;
   }

Tenga en cuenta que el nombre de Python para el objeto de excepción es
"spam.error". La función "PyErr_NewException()" puede crear una clase
con la clase base siendo "Exception" (a menos que se pase otra clase
en lugar de "NULL"), descrita en Excepciones incorporadas.

Tenga en cuenta también que la variable "SpamError" retiene una
referencia a la clase de excepción recién creada; esto es intencional!
Como la excepción podría eliminarse del módulo mediante un código
externo, se necesita una referencia propia de la clase para garantizar
que no se descarte, lo que hace que "SpamError" se convierta en un
puntero colgante. Si se convierte en un puntero colgante, el código C
que genera la excepción podría causar un volcado del núcleo u otros
efectos secundarios no deseados.

Discutimos el uso de "PyMODINIT_FUNC" como un tipo de retorno de
función más adelante en esta muestra.

La excepción "spam.error" se puede generar en su módulo de extensión
mediante una llamada a "PyErr_SetString()" como se muestra a
continuación:

   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. De vuelta al ejemplo
=========================

Volviendo a nuestra función de ejemplo, ahora debería poder comprender
esta declaración:

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

Retorna "NULL" (el indicador de error para las funciones que retornan
punteros de objeto) si se detecta un error en la lista de argumentos,
basándose en la excepción establecida por "PyArg_ParseTuple()". De lo
contrario, el valor de cadena del argumento se ha copiado en la
variable local "command". Esta es una asignación de puntero y no se
supone que modifique la cadena a la que apunta (por lo tanto, en el
Estándar C, la variable "command" debería declararse correctamente
como "const char * command").

La siguiente declaración es una llamada a la función Unix "system()",
pasándole la cadena que acabamos de obtener de "PyArg_ParseTuple()":

   sts = system(command);

Nuestra función "spam.system()" debe retornar el valor de "sts" como
un objeto Python. Esto se hace usando la función "PyLong_FromLong()".

   return PyLong_FromLong(sts);

En este caso, retornará un objeto entero. (Sí, ¡incluso los enteros
son objetos en el montículo (*heap*) en Python!)

Si tiene una función C que no retorna ningún argumento útil (una
función que retorna "void"), la función Python correspondiente debe
retornar "None". Necesita este modismo para hacerlo (que se implementa
mediante la macro "Py_RETURN_NONE"):

   Py_INCREF(Py_None);
   return Py_None;

"Py_None" es el nombre C para el objeto especial de Python "None". Es
un objeto genuino de Python en lugar de un puntero "NULL", que
significa "error" en la mayoría de los contextos, como hemos visto.


1.4. La tabla de métodos del módulo y la función de inicialización
==================================================================

Prometí mostrar cómo "spam_system()" se llama desde los programas de
Python. Primero, necesitamos enumerar su nombre y dirección en una
"tabla de métodos":

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

Tenga en cuenta la tercera entrada ("METH_VARARGS"). Esta es una
bandera que le dice al intérprete la convención de llamada que se
utilizará para la función C. Normalmente debería ser siempre
"METH_VARARGS" o "METH_VARARGS | METH_KEYWORDS"; un valor de "0"
significa que se usa una variante obsoleta de "PyArg_ParseTuple()".

Cuando se usa solo "METH_VARARGS", la función debe esperar que los
parámetros a nivel de Python se pasen como una tupla aceptable para el
análisis mediante "PyArg_ParseTuple()"; A continuación se proporciona
más información sobre esta función.

El bit "METH_KEYWORDS" se puede establecer en el tercer campo si se
deben pasar argumentos de palabras clave a la función. En este caso,
la función C debería aceptar un tercer parámetro "PyObject *" que será
un diccionario de palabras clave. Use "PyArg_ParseTupleAndKeywords()"
para analizar los argumentos de dicha función.

La tabla de métodos debe ser referenciada en la estructura de
definición del módulo:

   static struct PyModuleDef spammodule = {
       PyModuleDef_HEAD_INIT,
       "spam",   /* name of module */
       spam_doc, /* module documentation, may be NULL */
       -1,       /* size of per-interpreter state of the module,
                    or -1 if the module keeps state in global variables. */
       SpamMethods
   };

Esta estructura, a su vez, debe pasarse al intérprete en la función de
inicialización del módulo. La función de inicialización debe llamarse
"PyInit_name()", donde *name* es el nombre del módulo y debe ser el
único elemento no "static" definido en el archivo del módulo:

   PyMODINIT_FUNC
   PyInit_spam(void)
   {
       return PyModule_Create(&spammodule);
   }

Tenga en cuenta que PyMODINIT_FUNC declara la función como "PyObject
*" tipo de retorno, declara cualquier declaración de vinculación
especial requerida por la plataforma, y para C++ declara la función
como "extern "C"".

Cuando el programa Python importa el módulo "spam" por primera vez, se
llama "PyInit_spam()". (Consulte a continuación los comentarios sobre
la incorporación de Python). Llama a "PyModule_Create()", que retorna
un objeto de módulo e inserta objetos de función incorporados en el
módulo recién creado en función de la tabla (un arreglo de estructuras
"PyMethodDef") encontradas en la definición del módulo.
"PyModule_Create()" retorna un puntero al objeto del módulo que crea.
Puede abortar con un error fatal para ciertos errores, o retornar
"NULL" si el módulo no se pudo inicializar satisfactoriamente. La
función *init* debe retornar el objeto del módulo a su llamador, para
que luego se inserte en "sys.modules".

Al incrustar Python, la función "PyInit_spam()" no se llama
automáticamente a menos que haya una entrada en la tabla
"PyImport_Inittab". Para agregar el módulo a la tabla de
inicialización, use "PyImport_AppendInittab()", seguido opcionalmente
por una importación del módulo:

   int
   main(int argc, char *argv[])
   {
       wchar_t *program = Py_DecodeLocale(argv[0], NULL);
       if (program == NULL) {
           fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
           exit(1);
       }

       /* 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 */
       Py_SetProgramName(program);

       /* Initialize the Python interpreter.  Required.
          If this step fails, it will be a fatal error. */
       Py_Initialize();

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

       ...

       PyMem_RawFree(program);
       return 0;
   }

Nota:

  Eliminar entradas de "sys.modules" o importar módulos compilados en
  múltiples intérpretes dentro de un proceso (o seguir un "fork()" sin
  una intervención "exec()") puede crear problemas para algunas
  extensiones de módulos. Los autores de módulos de extensiones deben
  tener precaución al inicializar estructuras de datos internas.

Se incluye un módulo de ejemplo más sustancial en la distribución
fuente de Python como "Modules/xxmodule.c". Este archivo puede usarse
como plantilla o simplemente leerse como ejemplo.

Nota:

  A diferencia de nuestro ejemplo de "spam", "xxmodule" usa
  *inicialización de múltiples fases* (nuevo en Python 3.5), donde se
  retorna una estructura PyModuleDef de "PyInit_spam", y la creación
  del módulo se deja al maquinaria de importación. Para obtener
  detalles sobre la inicialización múltiples fases, consulte **PEP
  489**.


1.5. Compilación y Enlazamiento
===============================

Hay dos cosas más que hacer antes de que pueda usar su nueva
extensión: compilarla y vincularla con el sistema Python. Si usa carga
dinámica, los detalles pueden depender del estilo de carga dinámica
que usa su sistema; Para obtener más información al respecto, consulte
los capítulos sobre la creación de módulos de extensión (capítulo
Construyendo Extensiones C y C++) e información adicional que se
refiere solo a la construcción en Windows (capítulo Creación de
extensiones C y C++ en Windows).

Si no puede utilizar la carga dinámica, o si desea que su módulo sea
una parte permanente del intérprete de Python, tendrá que cambiar la
configuración (*setup*) y reconstruir el intérprete. Afortunadamente,
esto es muy simple en Unix: simplemente coloque su archivo
("spammodule.c" por ejemplo) en el directorio "Modules/ ` de una
distribución fuente desempaquetada, agregue una línea al archivo
:file:`Modules/Setup.local" que describe su archivo:

   spam spammodule.o

y reconstruya el intérprete ejecutando **make** en el directorio de
nivel superior. También puede ejecutar **make** en el subdirectorio
"Modules/", pero primero debe reconstruir "Makefile" ejecutando
'**make** Makefile'. (Esto es necesario cada vez que cambia el archivo
"Configuración").

Si su módulo requiere bibliotecas adicionales para vincular, también
se pueden enumerar en la línea del archivo de configuración, por
ejemplo:

   spam spammodule.o -lX11


1.6. Llamando funciones Python desde C
======================================

Hasta ahora nos hemos concentrado en hacer que las funciones de C
puedan llamarse desde Python. Lo contrario también es útil: llamar a
las funciones de Python desde C. Este es especialmente el caso de las
bibliotecas que admiten las llamadas funciones de "retrollamada". Si
una interfaz C utiliza retrollamadas, el Python equivalente a menudo
necesita proporcionar un mecanismo de retrollamada al programador de
Python; la implementación requerirá llamar a las funciones de
retrollamada de Python desde una retrollamada en C. Otros usos también
son imaginables.

Afortunadamente, el intérprete de Python se llama fácilmente de forma
recursiva, y hay una interfaz estándar para llamar a una función de
Python. (No me detendré en cómo llamar al analizador Python con una
cadena particular como entrada --- si está interesado, eche un vistazo
a la implementación de la opción de línea de comando "-c" en
"Modules/main.c" del código fuente de Python.)

Llamar a una función de Python es fácil. Primero, el programa Python
debe de alguna manera pasar el objeto de función Python. Debe
proporcionar una función (o alguna otra interfaz) para hacer esto.
Cuando se llama a esta función, guarde un puntero en el objeto de la
función Python (tenga cuidado de usar "Py_INCREF()") En una variable
global --- o donde mejor le parezca. Por ejemplo, la siguiente función
podría ser parte de una definición de módulo:

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

Esta función debe registrarse con el intérprete utilizando el
indicador "METH_VARARGS"; esto se describe en la sección La tabla de
métodos del módulo y la función de inicialización. La función
"PyArg_ParseTuple()" y sus argumentos están documentados en la sección
Extracción de parámetros en funciones de extensión.

Las macros "Py_XINCREF()" y "Py_XDECREF()" incrementan/disminuyen el
recuento de referencia de un objeto y son seguros en presencia de
punteros "NULL" (pero tenga en cuenta que *temp* no lo hará ser "NULL"
en este contexto). Más información sobre ellos en la sección Conteo de
Referencias.

Más tarde, cuando es hora de llamar a la función, llama a la función C
"PyObject_CallObject()". Esta función tiene dos argumentos, ambos
punteros a objetos arbitrarios de Python: la función Python y la lista
de argumentos. La lista de argumentos siempre debe ser un objeto de
tupla, cuya longitud es el número de argumentos. Para llamar a la
función Python sin argumentos, pase "NULL" o una tupla vacía; para
llamarlo con un argumento, pasa una tupla singleton. "Py_BuildValue()"
retorna una tupla cuando su cadena de formato consta de cero o más
códigos de formato entre paréntesis. Por ejemplo:

   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()" retorna un puntero de objeto Python: este es
el valor de retorno de la función Python. "PyObject_CallObject()" es
"recuento-referencia-neutral" con respecto a sus argumentos. En el
ejemplo, se creó una nueva tupla para servir como lista de argumentos,
a la cual se le llama "Py_DECREF()" inmediatamente después de la
llamada "PyObject_CallObject()".

El valor de retorno de "PyObject_CallObject()" es "nuevo": o bien es
un objeto nuevo o es un objeto existente cuyo recuento de referencias
se ha incrementado. Por lo tanto, a menos que desee guardarlo en una
variable global, debería de alguna manera "Py_DECREF()" el resultado,
incluso (¡especialmente!) Si no está interesado en su valor.

Sin embargo, antes de hacer esto, es importante verificar que el valor
de retorno no sea "NULL". Si es así, la función de Python terminó
generando una excepción. Si el código C que llamó
"PyObject_CallObject()" se llama desde Python, ahora debería retornar
una indicación de error a su llamador de Python, para que el
intérprete pueda imprimir un seguimiento de la pila, o el código de
Python que llama puede manejar la excepción. Si esto no es posible o
deseable, la excepción se debe eliminar llamando a "PyErr_Clear()".
Por ejemplo:

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

Dependiendo de la interfaz deseada para la función de retrollamada de
Python, es posible que también deba proporcionar una lista de
argumentos para "PyObject_CallObject()". En algunos casos, el programa
Python también proporciona la lista de argumentos, a través de la
misma interfaz que especificó la función de retrollamada. Luego se
puede guardar y usar de la misma manera que el objeto de función. En
otros casos, puede que tenga que construir una nueva tupla para
pasarla como lista de argumentos. La forma más sencilla de hacer esto
es llamar a "Py_BuildValue()". Por ejemplo, si desea pasar un código
de evento integral, puede usar el siguiente código:

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

¡Observe la ubicación de "Py_DECREF(arglist)" inmediatamente después
de la llamada, antes de la verificación de errores! También tenga en
cuenta que, estrictamente hablando, este código no está completo:
"Py_BuildValue()" puede quedarse sin memoria, y esto debe verificarse.

También puede llamar a una función con argumentos de palabras clave
utilizando "PyObject_Call()", que admite argumentos y argumentos de
palabras clave. Como en el ejemplo anterior, usamos "Py_BuildValue()"
para construir el diccionario.

   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. Extracción de parámetros en funciones de extensión
=======================================================

La función "PyArg_ParseTuple()" se declara de la siguiente manera:

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

El argumento *arg* debe ser un objeto de tupla que contenga una lista
de argumentos pasada de Python a una función C. El argumento *format*
debe ser una cadena de formato, cuya sintaxis se explica en Analizando
argumentos y construyendo valores en el Manual de referencia de la API
de Python/C. Los argumentos restantes deben ser direcciones de
variables cuyo tipo está determinado por la cadena de formato.

Tenga en cuenta que si bien "PyArg_ParseTuple()" verifica que los
argumentos de Python tengan los tipos requeridos, no puede verificar
la validez de las direcciones de las variables C pasadas a la llamada:
si comete errores allí, su código probablemente se bloqueará o al
menos sobrescribir bits aleatorios en la memoria. ¡Así que ten
cuidado!

Tenga en cuenta que las referencias de objetos de Python que se
proporcionan a quien llama son referencias prestadas (*borrowed*); ¡no
disminuya su recuento de referencias!

Algunas llamadas de ejemplo:

   #define PY_SSIZE_T_CLEAN  /* Make "s#" use Py_ssize_t rather than int. */
   #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. Parámetros de palabras clave para funciones de extensión
=============================================================

La función "PyArg_ParseTupleAndKeywords()" se declara de la siguiente
manera:

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

Los parámetros *arg* y *format* son idénticos a los de la función
"PyArg_ParseTuple()". El parámetro *kwdict* es el diccionario de
palabras clave recibidas como tercer parámetro del tiempo de ejecución
de Python. El parámetro *kwlist* es una lista de cadenas terminadas en
"NULL" que identifican los parámetros; los nombres se corresponden con
la información de tipo de *format* de izquierda a derecha. En caso de
éxito, "PyArg_ParseTupleAndKeywords()" retorna verdadero; de lo
contrario, retorna falso y genera una excepción apropiada.

Nota:

  ¡Las tuplas anidadas no se pueden analizar al usar argumentos de
  palabras clave! Los parámetros de palabras clave pasados que no
  están presentes en la *kwlist* provocarán que se genere "TypeError".

Aquí hay un módulo de ejemplo que usa palabras clave, basado en un
ejemplo de *Geoff Philbrick (philbrick@hks.com)*:

   #define PY_SSIZE_T_CLEAN  /* Make "s#" use Py_ssize_t rather than int. */
   #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 keywdargmodule = {
       PyModuleDef_HEAD_INIT,
       "keywdarg",
       NULL,
       -1,
       keywdarg_methods
   };

   PyMODINIT_FUNC
   PyInit_keywdarg(void)
   {
       return PyModule_Create(&keywdargmodule);
   }


1.9. Construyendo Valores Arbitrarios
=====================================

Esta función es la contraparte de "PyArg_ParseTuple()". Se declara de
la siguiente manera:

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

Reconoce un conjunto de unidades de formato similares a las
reconocidas por "PyArg_ParseTuple()", pero los argumentos (que son de
entrada a la función, no de salida) no deben ser punteros, solo
valores. Retorna un nuevo objeto Python, adecuado para regresar de una
función C llamada desde Python.

Una diferencia con "PyArg_ParseTuple()": mientras que este último
requiere que su primer argumento sea una tupla (ya que las listas de
argumentos de Python siempre se representan como tuplas internamente),
"Py_BuildValue()" no siempre construye una tupla . Construye una tupla
solo si su cadena de formato contiene dos o más unidades de formato.
Si la cadena de formato está vacía, retorna "None"; si contiene
exactamente una unidad de formato, retorna el objeto que describa esa
unidad de formato. Para forzarlo a retornar una tupla de tamaño 0 o
uno, agregar paréntesis a la cadena de formato.

Ejemplos (a la izquierda la llamada, a la derecha el valor de Python
resultante):

   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. Conteo de Referencias
===========================

En lenguajes como C o C++, el programador es responsable de la
asignación dinámica y la desasignación de memoria en el montón. En C,
esto se hace usando las funciones "malloc()" y "free()". En C++, los
operadores "new" y "delete" se usan esencialmente con el mismo
significado y restringiremos la siguiente discusión al caso C.

Cada bloque de memoria asignado con "malloc()" eventualmente debería
ser retorna al grupo de memoria disponible exactamente por una llamada
a "free()". Es importante llamar a "free()" en el momento adecuado. Si
se olvida la dirección de un bloque pero "free()" no se solicita, la
memoria que ocupa no se puede reutilizar hasta que finalice el
programa. Esto se llama *fuga de memoria*. Por otro lado, si un
programa llama "free()" para un bloque y luego continúa usando el
bloque, crea un conflicto con la reutilización del bloque a través de
otra llamada a "malloc()". Esto se llama *usando memoria liberada*.
Tiene las mismas malas consecuencias que hacer referencia a datos no
inicializados: volcados de núcleos, resultados incorrectos, bloqueos
misteriosos.

Las causas comunes de pérdidas de memoria son rutas inusuales a través
del código. Por ejemplo, una función puede asignar un bloque de
memoria, hacer algunos cálculos y luego liberar el bloque nuevamente.
Ahora, un cambio en los requisitos de la función puede agregar una
prueba al cálculo que detecta una condición de error y puede regresar
prematuramente de la función. Es fácil olvidar liberar el bloque de
memoria asignado al tomar esta salida prematura, especialmente cuando
se agrega más tarde al código. Tales filtraciones, una vez
introducidas, a menudo pasan desapercibidas durante mucho tiempo: la
salida del error se toma solo en una pequeña fracción de todas las
llamadas, y la mayoría de las máquinas modernas tienen mucha memoria
virtual, por lo que la filtración solo se hace evidente en un proceso
de larga ejecución que usa la función de fugas con frecuencia. Por lo
tanto, es importante evitar que se produzcan fugas mediante una
convención o estrategia de codificación que minimice este tipo de
errores.

Dado que Python hace un uso intensivo de "malloc()" y "free()",
necesita una estrategia para evitar pérdidas de memoria, así como el
uso de memoria liberada. El método elegido se llama *recuento de
referencias*. El principio es simple: cada objeto contiene un
contador, que se incrementa cuando se almacena una referencia al
objeto en algún lugar, y que se reduce cuando se elimina una
referencia al mismo. Cuando el contador llega a cero, la última
referencia al objeto se ha eliminado y el objeto se libera.

Una estrategia alternativa se llama *recolección automática de
basura*. (A veces, el recuento de referencias también se conoce como
una estrategia de recolección de basura, de ahí mi uso de "automático"
para distinguir los dos). La gran ventaja de la recolección automática
de basura es que el usuario no necesita llamar a "free()"
explícitamente. (Otra ventaja afirmada es una mejora en la velocidad o
el uso de la memoria; sin embargo, esto no es un hecho difícil). La
desventaja es que para C, no hay un recolector de basura automático
verdaderamente portátil, mientras que el conteo de referencias se
puede implementar de forma portátil (siempre que las funciones
"malloc()" y "free()" están disponibles --- que garantiza el estándar
C). Tal vez algún día un recolector de basura automático lo
suficientemente portátil estará disponible para C. Hasta entonces,
tendremos que vivir con recuentos de referencia.

Si bien Python utiliza la implementación tradicional de conteo de
referencias, también ofrece un detector de ciclos que funciona para
detectar ciclos de referencia. Esto permite que las aplicaciones no se
preocupen por crear referencias circulares directas o indirectas;
Estas son las debilidades de la recolección de basura implementada
utilizando solo el conteo de referencias. Los ciclos de referencia
consisten en objetos que contienen referencias (posiblemente
indirectas) a sí mismos, de modo que cada objeto en el ciclo tiene un
recuento de referencias que no es cero. Las implementaciones típicas
de recuento de referencias no pueden recuperar la memoria que
pertenece a algún objeto en un ciclo de referencia, o referenciada a
partir de los objetos en el ciclo, a pesar de que no hay más
referencias al ciclo en sí.

El detector de ciclos puede detectar ciclos de basura y puede
reclamarlos. El módulo "gc" expone una forma de ejecutar el detector
(la función "collect()"), así como las interfaces de configuración y
la capacidad de desactivar el detector en tiempo de ejecución. El
detector de ciclo se considera un componente opcional; aunque se
incluye de manera predeterminada, se puede deshabilitar en el momento
de la compilación utilizando la opción "--without-cycle-gc" al script
**configure** en plataformas Unix (incluido Mac OS X). Si el detector
de ciclos está deshabilitado de esta manera, el módulo "gc" no estará
disponible.


1.10.1. Conteo de Referencias en Python
---------------------------------------

Hay dos macros, "Py_INCREF(x)" y "Py_DECREF(x)", que manejan el
incremento y la disminución del recuento de referencias. "Py_DECREF()"
también libera el objeto cuando el recuento llega a cero. Por
flexibilidad, no llama a "free()" directamente --- más bien, realiza
una llamada a través de un puntero de función en el objeto *type
object*. Para este propósito (y otros), cada objeto también contiene
un puntero a su objeto de tipo.

La gran pregunta ahora permanece: ¿cuándo usar "Py_INCREF(x)" y
"Py_DECREF(x)"? Primero introduzcamos algunos términos. Nadie "posee"
un objeto; sin embargo, puede *poseer una referencia* a un objeto. El
recuento de referencias de un objeto ahora se define como el número de
referencias que posee. El propietario de una referencia es responsable
de llamar a "Py_DECREF()" cuando la referencia ya no es necesaria. La
propiedad de una referencia puede ser transferida. Hay tres formas de
deshacerse de una referencia de propiedad: pasarla, almacenarla o
llamar a "Py_DECREF()". Olvidar deshacerse de una referencia de
propiedad crea una pérdida de memoria.

También es posible *tomar prestada* [2] una referencia a un objeto. El
prestatario de una referencia no debe llamar a "Py_DECREF()". El
prestatario no debe retener el objeto por más tiempo que el
propietario del cual fue prestado. El uso de una referencia prestada
después de que el propietario la haya eliminado corre el riesgo de
usar memoria liberada y debe evitarse por completo [3].

La ventaja de pedir prestado sobre tener una referencia es que no
necesita ocuparse de disponer de la referencia en todas las rutas
posibles a través del código --- en otras palabras, con una referencia
prestada no corre el riesgo de fugas cuando se toma una salida
prematura. La desventaja de pedir prestado sobre la posesión es que
hay algunas situaciones sutiles en las que, en un código aparentemente
correcto, una referencia prestada se puede usar después de que el
propietario del que se tomó prestado la haya eliminado.

Una referencia prestada se puede cambiar en una referencia de
propiedad llamando a "Py_INCREF()". Esto no afecta el estado del
propietario del cual se tomó prestada la referencia: crea una nueva
referencia de propiedad y otorga responsabilidades completas al
propietario (el nuevo propietario debe disponer de la referencia
correctamente, así como el propietario anterior).


1.10.2. Reglas de Propiedad
---------------------------

Cuando una referencia de objeto se pasa dentro o fuera de una función,
es parte de la especificación de la interfaz de la función si la
propiedad se transfiere con la referencia o no.

La mayoría de las funciones que retornan una referencia a un objeto
pasan de propiedad con la referencia. En particular, todas las
funciones cuya función es crear un nuevo objeto, como
"PyLong_FromLong()" y "Py_BuildValue()", pasan la propiedad al
receptor. Incluso si el objeto no es realmente nuevo, aún recibirá la
propiedad de una nueva referencia a ese objeto. Por ejemplo,
"PyLong_FromLong()" mantiene un caché de valores populares y puede
retornar una referencia a un elemento en caché.

Muchas funciones que extraen objetos de otros objetos también
transfieren la propiedad con la referencia, por ejemplo
"PyObject_GetAttrString()". Sin embargo, la imagen es menos clara
aquí, ya que algunas rutinas comunes son excepciones:
"PyTuple_GetItem()", "PyList_GetItem()", "PyDict_GetItem()", y
"PyDict_GetItemString()" todas las referencias retornadas que tomaste
prestadas de la tupla, lista o diccionario.

La función "PyImport_AddModule()" también retorna una referencia
prestada, aunque en realidad puede crear el objeto que retorna: esto
es posible porque una referencia de propiedad del objeto se almacena
en "sys.modules".

Cuando pasa una referencia de objeto a otra función, en general, la
función toma prestada la referencia de usted --- si necesita
almacenarla, usará "Py_INCREF()" para convertirse en un propietario
independiente. Hay exactamente dos excepciones importantes a esta
regla: "PyTuple_SetItem()" y "PyList_SetItem()". Estas funciones se
hacen cargo de la propiedad del artículo que se les pasa, ¡incluso si
fallan! (Tenga en cuenta que "PyDict_SetItem()" y sus amigos no se
hacen cargo de la propiedad --- son "normales")

Cuando se llama a una función C desde Python, toma de la persona que
llama referencias a sus argumentos. Quien llama posee una referencia
al objeto, por lo que la vida útil de la referencia prestada está
garantizada hasta que la función regrese. Solo cuando dicha referencia
prestada debe almacenarse o transmitirse, debe convertirse en una
referencia propia llamando a "Py_INCREF()".

La referencia de objeto retornada desde una función C que se llama
desde Python debe ser una referencia de propiedad: la propiedad se
transfiere de la función a su llamador.


1.10.3. Hielo delgado
---------------------

Hay algunas situaciones en las que el uso aparentemente inofensivo de
una referencia prestada puede generar problemas. Todo esto tiene que
ver con invocaciones implícitas del intérprete, lo que puede hacer que
el propietario de una referencia se deshaga de él.

El primer y más importante caso que debe conocer es el uso de
"Py_DECREF()" en un objeto no relacionado mientras toma prestada una
referencia a un elemento de la lista. Por ejemplo:

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

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

Esta función primero toma prestada una referencia a "list[0]", luego
reemplaza "list[1]" con el valor "0", y finalmente imprime la
referencia prestada. Parece inofensivo, ¿verdad? ¡Pero no lo es!

Sigamos el flujo de control en "PyList_SetItem()". La lista posee
referencias a todos sus elementos, por lo que cuando se reemplaza el
elemento 1, debe deshacerse del elemento original 1. Ahora supongamos
que el elemento original 1 era una instancia de una clase definida por
el usuario, y supongamos además que la clase definió un método
"__del__()". Si esta instancia de clase tiene un recuento de
referencia de 1, al eliminarla llamará a su método "__del__()".

Como está escrito en Python, el método "__del__()" puede ejecutar
código arbitrario de Python. ¿Podría hacer algo para invalidar la
referencia a "item" en "error()"? ¡Tenlo por seguro! Suponiendo que la
lista pasado a "bug()" es accesible para el método "__del__()", podría
ejecutar una declaración en el sentido de "del list[0]", y suponiendo
que este fuera el última referencia a ese objeto, liberaría la memoria
asociada con él, invalidando así el "elemento".

La solución, una vez que conoce el origen del problema, es fácil:
incremente temporalmente el recuento de referencia. La versión
correcta de la función dice:

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

Esta es una historia real. Una versión anterior de Python contenía
variantes de este error y alguien pasó una cantidad considerable de
tiempo en un depurador C para descubrir por qué sus métodos
"__del__()" fallaban ...

El segundo caso de problemas con una referencia prestada es una
variante que involucra hilos. Normalmente, varios hilos en el
intérprete de Python no pueden interponerse entre sí, porque hay un
bloqueo global que protege todo el espacio de objetos de Python. Sin
embargo, es posible liberar temporalmente este bloqueo usando la macro
"Py_BEGIN_ALLOW_THREADS", y volver a adquirirlo usando
"Py_END_ALLOW_THREADS". Esto es común al bloquear las llamadas de E/S,
para permitir que otros subprocesos usen el procesador mientras
esperan que se complete la E/S. Obviamente, la siguiente función tiene
el mismo problema que la anterior:

   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. Punteros NULL
---------------------

En general, las funciones que toman referencias de objetos como
argumentos no esperan que les pase los punteros "NULL", y volcará el
núcleo (o causará volcados de núcleo posteriores) si lo hace. Las
funciones que retornan referencias a objetos generalmente retornan
"NULL" solo para indicar que ocurrió una excepción. La razón para no
probar los argumentos "NULL" es que las funciones a menudo pasan los
objetos que reciben a otra función --- si cada función probara "NULL",
habría muchas pruebas redundantes y el código correría más lentamente.

Es mejor probar "NULL" solo en "source:" cuando se recibe un puntero
que puede ser "NULL", por ejemplo, de "malloc()" o de una función que
puede plantear una excepción.

Las macros "Py_INCREF()" y "Py_DECREF()" no comprueban los punteros
"NULL" --- sin embargo, sus variantes "Py_XINCREF()" y "Py_XDECREF()"
lo hacen.

Las macros para verificar un tipo de objeto en particular
("Pytype_Check()") no verifican los punteros "NULL" --- nuevamente,
hay mucho código que llama a varios de estos en una fila para probar
un objeto contra varios tipos esperados diferentes, y esto generaría
pruebas redundantes. No hay variantes con comprobación "NULL".

El mecanismo de llamada a la función C garantiza que la lista de
argumentos pasada a las funciones C ("args" en los ejemplos) nunca sea
"NULL" --- de hecho, garantiza que siempre sea una tupla [4].

Es un error grave dejar que un puntero "NULL" "escape" al usuario de
Python.


1.11. Escribiendo Extensiones en C++
====================================

Es posible escribir módulos de extensión en C++. Se aplican algunas
restricciones. Si el compilador de C compila y vincula el programa
principal (el intérprete de Python), no se pueden usar objetos
globales o estáticos con constructores. Esto no es un problema si el
programa principal está vinculado por el compilador de C++. Las
funciones que serán llamadas por el intérprete de Python (en
particular, las funciones de inicialización del módulo) deben
declararse usando "extern "C"". No es necesario encerrar los archivos
de encabezado de Python en "extern "C" {...}" --- ya usan este
formulario si el símbolo "__cplusplus" está definido (todos los
compiladores recientes de C++ definen este símbolo) .


1.12. Proporcionar una API C para un módulo de extensión
========================================================

Muchos módulos de extensión solo proporcionan nuevas funciones y tipos
para ser utilizados desde Python, pero a veces el código en un módulo
de extensión puede ser útil para otros módulos de extensión. Por
ejemplo, un módulo de extensión podría implementar un tipo de
"colección" que funciona como listas sin orden. Al igual que el tipo
de lista Python estándar tiene una API C que permite a los módulos de
extensión crear y manipular listas, este nuevo tipo de colección debe
tener un conjunto de funciones C para la manipulación directa desde
otros módulos de extensión.

A primera vista, esto parece fácil: simplemente escriba las funciones
(sin declararlas "static", por supuesto), proporcione un archivo de
encabezado apropiado y documente la API de C. Y, de hecho, esto
funcionaría si todos los módulos de extensión siempre estuvieran
vinculados estáticamente con el intérprete de Python. Sin embargo,
cuando los módulos se usan como bibliotecas compartidas, los símbolos
definidos en un módulo pueden no ser visibles para otro módulo. Los
detalles de visibilidad dependen del sistema operativo; algunos
sistemas usan un espacio de nombres global para el intérprete de
Python y todos los módulos de extensión (Windows, por ejemplo),
mientras que otros requieren una lista explícita de símbolos
importados en el momento del enlace del módulo (AIX es un ejemplo) u
ofrecen una variedad de estrategias diferentes (la mayoría Unices). E
incluso si los símbolos son visibles a nivel mundial, ¡el módulo cuyas
funciones uno desea llamar podría no haberse cargado todavía!

Por lo tanto, la portabilidad requiere no hacer suposiciones sobre la
visibilidad del símbolo. Esto significa que todos los símbolos en los
módulos de extensión deben declararse "static", excepto la función de
inicialización del módulo, para evitar conflictos de nombres con otros
módulos de extensión (como se discutió en la sección La tabla de
métodos del módulo y la función de inicialización). Y significa que
los símbolos que *deberían* ser accesibles desde otros módulos de
extensión deben exportarse de una manera diferente.

Python proporciona un mecanismo especial para pasar información de
nivel C (punteros) de un módulo de extensión a otro: Cápsulas. Una
cápsula es un tipo de datos de Python que almacena un puntero ("void
*"). Las cápsulas solo se pueden crear y acceder a través de su API de
C, pero se pueden pasar como cualquier otro objeto de Python. En
particular, pueden asignarse a un nombre en el espacio de nombres de
un módulo de extensión. Otros módulos de extensión pueden importar
este módulo, recuperar el valor de este nombre y luego recuperar el
puntero de la Cápsula.

Hay muchas formas en que las Cápsulas se pueden usar para exportar la
API de C de un módulo de extensión. Cada función podría tener su
propia cápsula, o todos los punteros de API C podrían almacenarse en
una matriz cuya dirección se publica en una cápsula. Y las diversas
tareas de almacenamiento y recuperación de los punteros se pueden
distribuir de diferentes maneras entre el módulo que proporciona el
código y los módulos del cliente.

Sea cual sea el método que elija, es importante nombrar sus cápsulas
correctamente. La función "PyCapsule_New()" toma un parámetro de
nombre ("const char *"); se le permite pasar un nombre "NULL", pero le
recomendamos que especifique un nombre. Las cápsulas correctamente
nombradas proporcionan un grado de seguridad de tipo de tiempo de
ejecución; no hay una manera factible de distinguir una Cápsula sin
nombre de otra.

En particular, las cápsulas utilizadas para exponer las API de C deben
recibir un nombre siguiendo esta convención:

   modulename.attributename

La función de conveniencia "PyCapsule_Import()" facilita la carga de
una API C proporcionada a través de una cápsula, pero solo si el
nombre de la cápsula coincide con esta convención. Este comportamiento
brinda a los usuarios de C API un alto grado de certeza de que la
Cápsula que cargan contiene la API de C correcta.

El siguiente ejemplo demuestra un enfoque que pone la mayor parte de
la carga en el escritor del módulo de exportación, que es apropiado
para los módulos de biblioteca de uso común. Almacena todos los
punteros de API C (¡solo uno en el ejemplo!) En un arreglo de punteros
"void" que se convierte en el valor de una cápsula. El archivo de
encabezado correspondiente al módulo proporciona una macro que se
encarga de importar el módulo y recuperar sus punteros de API C; Los
módulos de cliente solo tienen que llamar a esta macro antes de
acceder a la API de C.

El módulo de exportación es una modificación del módulo "spam" de la
sección Un ejemplo simple. La función "spam.system()" no llama a la
función de la biblioteca C "system()" directamente, sino una función
"PySpam_System()", que por supuesto haría algo más complicado en
realidad (como agregar "spam" a cada comando). Esta función
"PySpam_System()" también se exporta a otros módulos de extensión.

La función "PySpam_System()" es una función C simple, declarada
"static" como todo lo demás:

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

La función "spam_system()" se modifica de manera trivial:

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

Al comienzo del módulo, justo después de la línea:

   #include <Python.h>

se deben agregar dos líneas más:

   #define SPAM_MODULE
   #include "spammodule.h"

El "#define" se usa para decirle al archivo de encabezado que se está
incluyendo en el módulo de exportación, no en un módulo de cliente.
Finalmente, la función de inicialización del módulo debe encargarse de
inicializar la matriz de punteros de API C:

   PyMODINIT_FUNC
   PyInit_spam(void)
   {
       PyObject *m;
       static void *PySpam_API[PySpam_API_pointers];
       PyObject *c_api_object;

       m = PyModule_Create(&spammodule);
       if (m == NULL)
           return NULL;

       /* 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_AddObject(m, "_C_API", c_api_object) < 0) {
           Py_XDECREF(c_api_object);
           Py_DECREF(m);
           return NULL;
       }

       return m;
   }

Tenga en cuenta que "PySpam_API" se declara "static"; de lo contrario,
la matriz de punteros desaparecería cuando "PyInit_spam()" finalice!

La mayor parte del trabajo está en el archivo de encabezado
"spammodule.h", que se ve así:

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

Todo lo que un módulo cliente debe hacer para tener acceso a la
función "PySpam_System()" es llamar a la función (o más bien macro)
"import_spam()" en su función de inicialización:

   PyMODINIT_FUNC
   PyInit_client(void)
   {
       PyObject *m;

       m = PyModule_Create(&clientmodule);
       if (m == NULL)
           return NULL;
       if (import_spam() < 0)
           return NULL;
       /* additional initialization can happen here */
       return m;
   }

La principal desventaja de este enfoque es que el archivo
"spammodule.h" es bastante complicado. Sin embargo, la estructura
básica es la misma para cada función que se exporta, por lo que solo
se debe aprender una vez.

Finalmente, debe mencionarse que las cápsulas ofrecen una
funcionalidad adicional, que es especialmente útil para la asignación
de memoria y la desasignación del puntero almacenado en una cápsula.
Los detalles se describen en el Manual de referencia de Python/C API
en la sección Cápsulas y en la implementación de Capsules (archivos
"Include/pycapsule.h" y "Objects/pycapsule.c" en la distribución del
código fuente de Python).

-[ Notas al pie de página ]-

[1] Ya existe una interfaz para esta función en el módulo estándar
    "os" --- se eligió como un ejemplo simple y directo.

[2] La metáfora de "pedir prestado" una referencia no es completamente
    correcta: el propietario todavía tiene una copia de la referencia.

[3] ¡Comprobar que el recuento de referencia es al menos 1 **no
    funciona** --- el recuento de referencia en sí podría estar en la
    memoria liberada y, por lo tanto, puede reutilizarse para otro
    objeto!

[4] Estas garantías no se cumplen cuando utiliza la convención de
    llamadas de estilo "antiguo", que todavía se encuentra en muchos
    códigos existentes.
