Python C Api检查PyObject是否指向特定的PyCFunction

问题描述

我有一个使用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,{NULL,NULL,NULL} /* sentinel */
};

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

作为参数之一,用户可以传递一个函数,例如:

my_func1(my_func2)

如何在my_func1内部检测到用户传递的参数是一个函数,并使用Python C API指向my_func2

解决方法

您可以使用PyCFunction_Check测试对象是否为C函数,并使用PyCFunction_GetFunction获取C函数指针。然后,您可以只比较C函数指针。如果要查看签名,则相关标头位于https://github.com/python/cpython/blob/4c9ea093cd752a6687864674d34250653653f743/Include/methodobject.h

这看起来至少可以追溯到Python 3.6(可能更远),因为它已经稍微移动了定义的标头,因此很难跟踪。

请注意,所有这些看起来都没有记载,因此您不应该完全依赖它的不变。