Llamar a Python desde C | Serie 1

En este artículo, nos centraremos principalmente en la ejecución segura de Python invocable desde C, devolviendo un resultado a C y escribiendo código C que necesita acceder a una función de Python como devolución de llamada.

El siguiente código se enfoca en las partes complicadas involucradas en llamar a Python desde C.

Código n.º 1: [Paso 1 y 2] Poseer el GIL y verificar que la función sea invocable correctamente

#include <Python.h>
  
/* Execute func(x, y) in the Python interpreter. The
arguments and return result of the function must
be Python floats */
  
double call_func(PyObject *func, double x, double y)
{
    PyObject *args;
    PyObject *kwargs;
    PyObject *result = 0;
    double retval;
      
    // Make sure we own the GIL
    PyGILState_STATE state = PyGILState_Ensure();
      
      
    // Verify that func is a proper callable
    if (!PyCallable_Check(func))
    {
        fprintf(stderr, "call_func: expected a callable\n");
        goto fail;
    }

 
Código n.º 2: construcción de argumentos, función de llamada, verificación de excepciones de Python

Cree el valor de retorno, restaure el estado GIL anterior y regrese.

    // Step3
    args = Py_BuildValue("(dd)", x, y);
    kwargs = NULL;
      
    // Step 4
    result = PyObject_Call(func, args, kwargs);
    Py_DECREF(args);
    Py_XDECREF(kwargs);
      
    // Step 5
    if (PyErr_Occurred())
    {
        PyErr_Print();
        goto fail;
    }
      
    // Verify the result is a float object 
    if (!PyFloat_Check(result))
    {
        fprintf(stderr, "call_func: callable didn't return a float\n");
        goto fail;
    }
      
    // Step 6
    retval = PyFloat_AsDouble(result);
    Py_DECREF(result);
      
    // Step 7
    PyGILState_Release(state);
    return retval;
    fail:
        Py_XDECREF(result);
        PyGILState_Release(state);
        abort(); 
}

Se debe pasar una referencia a un Python invocable existente para usar esta función. Para hacerlo, hay muchas maneras, como simplemente escribir código C para extraer un símbolo de un módulo existente o pasar un objeto invocable a un módulo de extensión.
 
El código que se proporciona a continuación muestra cómo llamar a una función desde un intérprete de Python integrado.

Código #3: Cargando un símbolo desde un módulo

#include <Python.h>
/* Definition of call_func() same as above */
  
/* Load a symbol from a module */
PyObject *import_name(const char *modname, const char *symbol)
{
    PyObject *u_name, *module;
    u_name = PyUnicode_FromString(modname);
    module = PyImport_Import(u_name);
    Py_DECREF(u_name);
      
    return PyObject_GetAttrString(module, symbol);
}

Publicación traducida automáticamente

Artículo escrito por manikachandna97 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *