检查PyObject是否是nullptr

Checking if PyObject is nullptr

本文关键字:nullptr 是否是 PyObject 检查      更新时间:2023-10-16

我使用Python C Api来填充包含PyObject*元素的列表并将其转移到Python中的函数。一切都进行得很顺利,但是有一个问题——Python中的转移列表包含奇数<NULL>项。列表也包含了"通缉"对象,所以它看起来几乎可以工作了。

这是列表预览:

[<NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <dbg.TBack object at 0x19675870>, <interface.Grid object at 0x196758B0>, <interface.Grid object at 0x196758F0>, <interface.slp object at 0x196757D0>]

我用来填充Python C API列表的代码。

PyObject* list = PyList_New(objectsList.size());
PyObject* handle;
for (auto child : objectsList) {
    if (!child) {
        continue;
    }
    handle = child->GetHandle(); // handle = PyObject*
    if (!handle) {
        continue;
    }
    PyList_Append(list, handle);
}
return list; // push

我试过添加if(!handle)检查,但在实践中似乎没有任何结果。

问题:我如何才能摆脱我的列表中的<NULL>条目?

试试这个方案

if (handle == Py_None) {
    continue;
}   

PyObject_Not(PyObject *o)

如果对象0被认为为真则返回0,否则返回1。这相当于Python表达式not o。如果失败,返回-1。

否则,也许您可以检查handle的字符串表示。根据文档,您可能能够使用

的某些组合
int       PyObject_Compare(PyObject *o1, PyObject *o2)
PyObject* PyObject_Repr   (PyObject *o)

我在想

PyObject* null_str   = Py_BuildValue("null_str", "<NULL>");
PyObject* handle_str = PyObject_Repr(handle);
if (!PyObject_Compare(null_str, handle_str)) {
    continue;
}

问题在于如何分配列表。PyList_New(Py_ssize_t len)的文档:

注意:如果len大于0,返回的list对象的项被设为NULL。因此,在使用PyList_SetItem()将所有项设置为实际对象之前,您不能使用抽象API函数(如PySequence_SetItem())或将对象暴露给Python代码。

。它正在创建一个"len"空指针列表,而不是创建一个具有预分配空间的空列表。

解决方案是:

  1. 创建一个空列表(传递len 0)并保持代码的其余部分相同(使用PyList_Append),或者
  2. 为列表分配一个大小,并使用PyList_SetItem代替append。如果您使用这种方法,请注意PyList_setItem窃取了引用(因此您必须使用incref handle),并且您想要的列表长度仅包括具有getHandle()!=NULL的对象。