1

I have a module written using the Python C API:

static PyObject* my_func1(PyObject* /*self*/, PyObject* args)
{
  Py_RETURN_NONE;
}

static PyObject* my_func2(PyObject* /*self*/, PyObject* args)
{
  Py_RETURN_NONE;
}


static PyMethodDef methods[] = {
    {"my_func1", (PyCFunction)my_func1, METH_VARARGS, ""}, 
    {"my_func2", (PyCFunction)my_func2, METH_VARARGS, ""},
    {NULL, NULL, 0, NULL} /* sentinel */
};

static struct PyModuleDef moduledef = {                                                          
      PyModuleDef_HEAD_INIT, my_module, NULL, -1, methods, NULL, NULL, NULL, NULL
};                     
 
PyMODINIT_FUNC PyInit_my_module(void){                                                                                                
    return PyModule_Create(&moduledef);                                                            
}

as one of the arguments a user can pass a function e.g.:

my_func1(my_func2)

How can I detect inside my_func1, that the argument the user passed is a function, that points to my_func2 using the Python C API?

maxbachmann
  • 2,862
  • 1
  • 11
  • 35

1 Answers1

2

You can use PyCFunction_Check to test if an object is a C function and PyCFunction_GetFunction to get the C function pointer. You can then just compare the C function pointers. Relevant header is at https://github.com/python/cpython/blob/4c9ea093cd752a6687864674d34250653653f743/Include/methodobject.h if you want to look at the signatures.

This looks to date back to at least Python 3.6 (probably further) although it's slightly hard to track because they've moved what headers these are defined in a bit.

Note that this is all looks fairly undocumented so you shouldn't rely completely on it not changing.

DavidW
  • 29,336
  • 6
  • 55
  • 86
  • Thanks this is exactly what I was searching for. As a note this works for me both in python2.7 and python3.5 aswell – maxbachmann Nov 08 '20 at 19:04