1.6 Llamar a funciones de Python desde C

Hasta ahora, nos hemos concentrado en hacer las funciones en C accesibles desde Python. También lo contrario, llamar a las funciones de Python desde C, es útil. Esto es el caso concreto de las bibliotecas con el concepto de llamadas de ``respuesta''. Si una interfaz de C utiliza respuestas, el Python equivalente suele tener que proporcionar un mecanismo de respuesta para el programador de Python. La implementación requerirá llamar a las funciones de repuesta desde las funciones de respuesta en C. Existen otros usos.

Afortunadamente, es sencillo llamar al intérprete de Python recursivamente y existe una interfaz estándar para llamar a una función de Python. No voy a insistir en cómo llamar al analizador de Python con una cadena concreta como entrada; en caso de interés, consultar la implementación de la opción de línea de órdenes -c en el fichero Python/pythonmain.c del código fuente de Python.

Es fácil llamar a una función de Python. Para empezar, el programa Python debe pasar de algún modo el objeto función de Python. Se debe proporcionar una función (u otra interfaz) para lograrlo. En dicha función se debe guardar un puntero al objeto función de Python (ojo, hay que hacer Py_INCREF()) en una variable global, u otro lugar adecuado. 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(dummy, args)
    PyObject *dummy, *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 estar registrada en el intérprete mediante el indicador METH_VARARGS, lo que se describe en la sección , ``La tabla de métodos y la función de inicialización del módulo ''. La función PyArg_ParseTuple() y sus argumentos están documentados en la sección  ``Cadenas de formato de PyArg_ParseTuple()''.

Las macros Py_XINCREF() y Py_XDECREF() incrementan/decrementan el saldo de referencias de un objeto y son seguras en la presencia de punteros NULL (obsérvese que temp no será NULL en este contexto). Hay más información en la sección , ``Saldos de referencias.''

Más tarde cuando toque evaluar la función, se debe llamar a la función C PyEval_CallObject(). Esta función toma dos argumentos, los dos punteros a objetos de Python arbitrarios: la función Python y la lista de argumentos. La lista de argumentos siempre debe ser un objeto tupla cuya longitud sea el número de argumentos. Para llamar a la función de Python si argumentos, se debe pasar una tupla vacía. Para pasar un solo argumento, se debe pasar una tupla de un solo elemento. Py_BuildValue() devuelve 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;
    ...
    /* Hora de la llamada de respuesta */
    arglist = Py_BuildValue("(i)", arg);
    result = PyEval_CallObject(my_callback, arglist);
    Py_DECREF(arglist);

PyEval_CallObject() devuelve un puntero a objeto Python: el valor devuelto por la función de Python. PyEval_CallObject() es neutro respecto al saldo de referencias de sus argumentos. En el ejemplo, se crea una nueva tupla para servir de lista de argumentos, que sufre una llamada a Py_DECREF() inmediatamente tras la llamada.

El valor devuelto por PyEval_CallObject() es ``nuevo'': bien es un objeto completamente nuevo o es un objeto existente cuyo saldo de referencias se ha incrementado. Por ello, salvo que se vaya a guardar el objeto en una variable global, se debe someter el resultado a Py_DECREF(), incluso (¡más aún!) si no se está interesado en el valor.

Antes de hacerlo, sin embargo, es importante comprobar que el valor no es NULL. De serlo, la función termino su ejecución con una excepción. Si el código C que llamó a PyEval_CallObject() fue llamado desde Python, debería devolver una indicación de error a su llamante Python, para que el intérprete sea capaz de presentar la información de la excepción o el código Python sea capaz de gestionar la excepción. Si esto no es posible o conveniente, debería limpiarse la excepción llamando a PyErr_Clear(). Por ejemplo:

    if (result == NULL)
        return NULL; /* Remitir el error */
    ...use result...
    Py_DECREF(result);

Dependiendo de la interfaz con la función de respuesta de Python deseada, puede que se tenga que proporcionar una lista de argumentos para PyEval_CallObject(). En ciertos casos, también el programa en Python proporciona la lista de argumentos, a través de la misma interfaz especificada por la función de respuesta. Así, puede guardarse y utilizarse del mismo modo que el objeto función. En otros casos, puede que haya que construir una nueva tupla para pasar la lista de argumentos.El modo más sencillo de hacerlo es llamar a Py_BuildValue(). Por ejemplo, si se desea pasar un código de suceso entero, puede usarse el siguiente código:

    PyObject *arglist;
    ...
    arglist = Py_BuildValue("(l)", eventcode);
    result = PyEval_CallObject(my_callback, arglist);
    Py_DECREF(arglist);
    if (result == NULL)
        return NULL; /* Devolver el error */
    /* Aquí se puede usar el resultado */
    Py_DECREF(result);

Obsérvese la colocación de "Py_DECREF(arglist)" inmediatamente tras la llamada y antes de la comprobación de errores. También debe destacarse que el código no está completo estrictamente: puede agotarse la memoria en Py_BuildValue(), lo que debería comprobase.


Ver Sobre este documento... para obtener información sobre sugerencias.