Calling Python from C | Set 1

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



filter_none

edit
close

play_arrow

link
brightness_4
code

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

chevron_right


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

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

filter_none

edit
close

play_arrow

link
brightness_4
code

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

chevron_right


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

filter_none

edit
close

play_arrow

link
brightness_4
code

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

chevron_right




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.


Article Tags :

Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.