Calling Python from C | Set 1

Python Methods and Functions

The code below focuses on the tricky parts that involve calling Python from C.

Code # 1: [Step 1 & 2] Have the GIL and make sure the function is called correctly

# include & lt; Python.h & gt; 

 
/ * Execute func (x, y) in a Python interpreter.
the arguments and return result of the function should
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 (); 

 

 

// Check that func is called correctly

if (! PyCallable_Check (func))

{

  fprintf (stderr, "call_func: expected a callable" ); 

goto fail; 

}

Code # 2: Create Arguments, Call a Function, Check for Python Exceptions

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

  // Step 3

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; 

}

 

  // Check that the result is a float

if (! PyFloat_Check (result))

{

fprintf (stderr, "call_func: callable didn't return a float " ); 

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

}

An existing Python callable must be passed in order to use this function. There are many ways to do this, such as — just write C code to extract a symbol from an existing module, or pass a callable to an extension module.

The code below demonstrates calling a function from the built-in Python interpreter.

Code # 3: Loading a symbol from a module

# include & lt; Python.h & gt; 
/ * The definition of call_func () is the same as above * /

 
/ * Load symbol from 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); 

}