Open In App

Calling Python from C | Set 2

Improve
Improve
Like Article
Like
Save
Share
Report

Prerequisite: Calling Python from C | Set 1

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.

Code #1 : Simple embedding example




int main()
{
    PyObject * pow_func;
    double x;
    Py_Initialize();
      
    // Get a reference to the math.pow function
    pow_func = import_name("math", "pow");
      
    // Call it using our call_func() code 
    for (x = 0.0; x < 10.0; x += 0.1)
    {
        printf("% 0.2f % 0.2f\n", x, call_func(pow_func, x, 2.0));
    }
          
    Py_DECREF(pow_func);
    Py_Finalize();
    return 0;
}


 
To build this last example, C needs to be compiled and link against the Python interpreter. The snippet below shows how to do it (this is something that might require some amount of fiddling with on your machine):

Code #2 :




all::
cc -g embed.c -I/usr/local/include/python3.3m \
-L /usr/local/lib/python3.3/config-3.3m -lpython3.3m


Compiling and running the resulting executable gives output as :

0.00 0.00
0.10 0.01
0.20 0.04
0.30 0.09
0.40 0.16
...

 
There is another example given by the code below that shows an extension function that receives a callable and some arguments and passes them to call_func() for the purposes of testing.

Code #3 :




/* Extension function for testing the C-Python callback */
  
PyObject * py_call_func(PyObject * self, PyObject * args)
{
    PyObject * func;
  
    double x, y, result;
    if (! PyArg_ParseTuple(args, "Odd", &func, &x, &y))
    {
        return NULL;
    }
    result = call_func(func, x, y);
    return Py_BuildValue("d", result);
}


 
Code #4 : Testing the extension function




import work
  
def add(x, y):
    return x + y
  
work.call_func(add, 3, 4)


Output :

7.0

 
It is critical that first we need to have a Python object representing the callable that is to be invoked. This could be a function, class, method, built-in method, or anything that implements the __call__() operation. To verify whether it is a callable function use PyCallable_Check().

Code #5 : Checking PyCallable_Check() function




double call_func(PyObject *func, double x, double y)
{
    ...
    // Verify that func is a proper callable
    if (!PyCallable_Check(func))
    {
        fprintf(stderr, "call_func: expected a callable\n");
        goto fail;
    }
    ...


 
Simply use PyObject_Call() to call a function, supplying it with the callable object, a tuple of arguments, and an optional dictionary of keyword arguments.

Py_BuildValue() can be used to build the argument tuple or dictionary.

Code #6 :




double call_func(PyObject *func, double x, double y)
    {
        PyObject *args;
        PyObject *kwargs;
          
        /* Build arguments */
        args = Py_BuildValue("(dd)", x, y);
        kwargs = NULL;
        /* Call the function */
        result = PyObject_Call(func, args, kwargs);
        Py_DECREF(args);
        Py_XDECREF(kwargs);
         
          
        /* Check for Python exceptions (if any) */
        if (PyErr_Occurred())
        {
            PyErr_Print();
            goto fail;
        }
          
    fail:
        PyGILState_Release(state);
        abort();
          
    }




Last Updated : 27 Mar, 2019
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads