Python C API : How to check if an object is an instance of a type

标签 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 不是 MyType 定义的类的实例。

完整的 C++ 代码:

#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;
}

编译成cpp.so,并在Python中测试:

>>> import cpp
>>> isinstance(cpp.My(), cpp.My)
True
>>> cpp.checkMy(cpp.My())
False

最佳答案

METH_VARARGS

This is the typical calling convention, where the methods have the type PyCFunction. The function expects two PyObject* values. The first one is the self object for methods; for module functions, it is the module object. The second parameter (often called args) is a tuple object representing all arguments. This parameter is typically processed using PyArg_ParseTuple() or 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 }
};

关于Python C API : How to check if an object is an instance of a type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56214129/

相关文章:

c++ - 为什么不能将圆括号正确地视为构造函数调用?

python - C++ Python 嵌入 : Run on machine with no Python?

python - 屏蔽矩阵行中的最小值

python - 启动 python 控制台并控制其输出

c++ - C++中具有输出限制的排列

c++ - 如何设置模板参数,灵活选择不同种类的函数

python - 在c中读取python的全局变量

Python C api - 函数重载

python - 好友列表不完整 Facebook Graph API

python - 我正在尝试在 Mac OS 10.6.3 上安装 psycopg2;它声称找不到 "stdarg.h"但我可以看到它在那里;我应该怎么办?