Python C API:如何检查对象是否是类型的实例

时间:2019-05-20 03:57:44

标签: python c++ python-c-api

我想检查一个对象是否是某个类的实例。在Python中,我可以使用instanceof来做到这一点。在C / C ++中,我发现了一个名为PyObject_IsInstance的函数。但这似乎不像isinstance那样起作用。

详细信息(以下也称为示例代码):

  1. 在C ++中,我定义了自定义类型My。类型定义为MyType,对象定义为MyObject
  2. MyType添加到名称为My的导出模块中。
  3. 在Python中,创建一个新实例my = My(),然后isinstance(my, My)返回True
  4. 在C ++中,我们使用PyObject_IsInstance(my, (PyObject*)&MyType)检查my,并返回0,这意味着my不是{{1}定义的类的实例}。

完整的C ++代码:

MyType

将其编译为#define PY_SSIZE_T_CLEAN #include <python3.6/Python.h> #include <python3.6/structmember.h> #include <stddef.h> typedef struct { PyObject_HEAD int num; } MyObject; static PyTypeObject MyType = []{ PyTypeObject ret = { PyVarObject_HEAD_INIT(NULL, 0) }; ret.tp_name = "cpp.My"; ret.tp_doc = NULL; ret.tp_basicsize = sizeof(MyObject); ret.tp_itemsize = 0; ret.tp_flags = Py_TPFLAGS_DEFAULT; ret.tp_new = PyType_GenericNew; return ret; }(); // check if obj is an instance of MyType static PyObject *Py_fn_checkMy(PyObject *obj) { if (PyObject_IsInstance(obj, (PyObject *)&MyType)) Py_RETURN_TRUE; else Py_RETURN_FALSE; } static PyMethodDef modmethodsdef[] = { { "checkMy", (PyCFunction)Py_fn_checkMy, METH_VARARGS, NULL }, { NULL } }; static PyModuleDef moddef = []{ PyModuleDef ret = { PyModuleDef_HEAD_INIT }; ret.m_name = "cpp"; ret.m_doc = NULL; ret.m_size = -1; return ret; }(); PyMODINIT_FUNC PyInit_cpp(void) { PyObject *mod; if (PyType_Ready(&MyType) < 0) return NULL; mod = PyModule_Create(&moddef); if (mod == NULL) return NULL; Py_INCREF(&MyType); PyModule_AddObject(mod, "My", (PyObject *)&MyType); PyModule_AddFunctions(mod, modmethodsdef); return mod; } ,并在Python中对其进行测试:

cpp.so

1 个答案:

答案 0 :(得分:1)

METH_VARARGS

  

这是典型的调用约定,其中方法的类型为PyCFunction。该函数需要两个PyObject*值。第一个是方法的自我对象;第二个是方法的自我对象。对于模块功能,它是模块对象。第二个参数(通常称为args)是表示所有参数的元组对象。通常使用PyArg_ParseTuple()PyArg_UnpackTuple()处理此参数。

Py_fn_checkMy的功能签名与此不匹配。它需要两个参数。第一个是模块,这就是您要检查的MyType。第二个参数(您实际上并不接受)是一个包含您传递的对象的元组。您应该从元组中提取参数,并检查其类型。

使用METH_O指定单个参数而不是从元组提取参数可能会更好:

static PyObject *Py_fn_checkMy(PyObject *self, PyObject *obj) {
    if (PyObject_IsInstance(obj, (PyObject *)&MyType)) Py_RETURN_TRUE;
    else Py_RETURN_FALSE;
}


static PyMethodDef modmethodsdef[] = {
    { "checkMy", (PyCFunction)Py_fn_checkMy, METH_O, NULL },
    { NULL }
};