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