3

I am using a Python C Api to fill the list containing the PyObject* elements and transfer it to the function in Python. Everything went very smoothly but there is one issue - transfered list in Python is containing odd <NULL> entries. List is containing "wanted" objects as well so it looks like it's almost-working.

This is the list preview:

[<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>]

Code I am using for filling the list in 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

I have tried adding if(!handle) checks but it doesn't seem to have any result in practise.

Question: How can I get rid of the <NULL> entries in my list?

2 Answers 2

2

Try this solution

if (handle == Py_None) {
    continue;
}   

Or

int PyObject_Not(PyObject *o)

Returns 0 if the object o is considered to be true, and 1 otherwise. This is equivalent to the Python expression not o. On failure, return -1.

Otherwise, maybe you could check handle's string representation. According to the documentation, you might be able to use some combination of

int       PyObject_Compare(PyObject *o1, PyObject *o2)
PyObject* PyObject_Repr   (PyObject *o)

I'm thinking something like

PyObject* null_str   = Py_BuildValue("null_str", "<NULL>");
PyObject* handle_str = PyObject_Repr(handle);
if (!PyObject_Compare(null_str, handle_str)) {
    continue;
}
Sign up to request clarification or add additional context in comments.

Comments

1

The issue is in how you allocate the list. From the documentation for PyList_New(Py_ssize_t len):

Note: If len is greater than zero, the returned list object’s items are set to NULL. Thus you cannot use abstract API functions such as PySequence_SetItem() or expose the object to Python code before setting all items to a real object with PyList_SetItem().

I.e. it's making a list of "len" null pointers, rather than making an empty list with preallocated space.

The solution is either:

  1. make an empty list (pass len 0) and keep the rest of your code the same (using PyList_Append), or
  2. allocate the list with a size, and use PyList_SetItem instead of append. It you use this approach be aware that PyList_setItem steals a reference (so you'll have to incref handle), and that the length of the list you want only includes those objects with getHandle()!=NULL.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.