0

I am working on a project which requires Python with C integration. I have got it mostly working except for one issue below: How do I get the string representation of the callback function object in the C code. (See my comment in the code)

import mymodule
c=0

def double_it():
   c = c * 2
   return

def multiply(a, b):
   global c
   c = a*b
   mymodule.print_result(c, double_it)
   return

Where mymodule.print_result is defined as:

static PyObject*
print_result(PyObject* self, PyObject* args)
{
    PyObject *pCallBackFunc, *pArgs;
    int restult;
    char *func_name = NULL; // I want to fill this

    if (!PyArg_ParseTuple(args, "iO", &result, &pCallBackFunc))
    {
         printf ("ERRPR\n");
         return NULL;
     }

 if (PyCallable_Check(pCallBackFunc)) {
    Py_XINCREF(pCallBackFunc);

     // func_name = .... How to get the of the call back function that is "double_it" ??? 

   PyObject_CallObject(pCallBackFunc, pArgs);
   Py_XDECREF(pCallBackFunc);
   return Py_None;
}

Any help is greatly appreciated.

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
PySandy
  • 23
  • 3
  • You could use the representation of the object instead of its name, if it has one at all. – tynn Oct 02 '15 at 09:06

2 Answers2

2

Same way you would do it in Python, but in C instead.

PyObject_GetAttrString(pCallBackFunc, "__name__")
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
1

You could look at how the func_get_name function is implemented.

So to access the name of a function simply use:

PyObject *
get_function_name(PyFunctionObject *fun) {
    Py_INCREF(fun->func_name);
    return fun->func_name;
}

To be used as:

if (!PyArg_ParseTuple(args, "iO", &result, &pCallBackFunc))
{
     printf ("ERRPR\n");
     return NULL;
}

if (PyFunction_Check(pCallBackFunc)) {

   func_name = get_function_name((PyFunctionObject *)pCallBackFunc);

   PyObject_CallObject(pCallBackFunc, pArgs);
   Py_RETURN_NONE;
}

However func_name is a PyObject *. So you'd have to also convert it into a char *.


Note: you do not want to use PyCallable_Check because only functions have a name. Other callables need not have it. If you want to be able to handle generic callables and obtain the name only in the case of functions you still have to explicitly check for PyFunctions and then for generic callables.


The above solution avoids the attribute lookup and thus it should be quite more efficient than calling PyObject_GetAttr*.

Bakuriu
  • 98,325
  • 22
  • 197
  • 231