Open In App
Related Articles

Calling Python from C | Set 1

Improve Article
Save Article
Like Article

In this article, we will mainly focus on safe execution of a Python callable from C, returning a result back to C and writing C code that needs to access a Python function as a callback.

The code below focuses on the tricky parts that are involved in calling Python from C.

Code #1 : [Step 1 and 2] Own the GIL and Verify that function is a proper callable

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

Code #2 : Building Arguments, calling function, Check for Python exceptions

Create the return value, Restore previous GIL state and return.

    // Step3
    args = Py_BuildValue("(dd)", x, y);
    kwargs = NULL;
    // Step 4
    result = PyObject_Call(func, args, kwargs);
    // Step 5
    if (PyErr_Occurred())
        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);
    // Step 7
    return retval;

A reference to an existing Python callable needs to be passed in, to use this function. To do that there are many ways like – simply writing C code to extract a symbol from an existing module or having a callable object passed into an extension module.
The code given below shows calling a function from an embedded Python interpreter.

Code #3 : Loading a symbol from a module

#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);
    return PyObject_GetAttrString(module, symbol);

Last Updated : 27 Mar, 2019
Like Article
Save Article
Similar Reads
Related Tutorials