abstract classes and caller_owns return =False

Asked by Stefan Stiene

Hi,
I have the following problem:

A class method returns a pointer of an other abstract base class. This pointer is afterwards casted into a special subclass.

If I wrap this method with

caller_owns_return = False

Pybindgen creates the following code:

    retval = self->obj->getFoo();
    if (!(retval)) {
        Py_INCREF(Py_None);
        return Py_None;
    }
    py_Foo = PyObject_New(PyFoo, &PyFoo_Type);
    py_Foo->obj = new Foo(*retval);
    py_retval = Py_BuildValue((char *) "N", py_Foo);
    return py_retval;

Due to py_Foo->obj = new Foo(*retval); I get the compile error:
 error C2259: 'Foo': cannot instantiate abstract class

If I choose caller_owns_return = True the line changes to:
py_Foo->obj = retval;

This compiles and runs.However when the foo object is deleted by python I get a python runtime error since the object is also deleted on c++ side. Changing this on c++ side is not possible.

Is it possible to say caller_owns_return = True and force pybindgen not to delete the object?

Hope I made my point clear.
stefan

Question information

Language:
English Edit question
Status:
Solved
For:
PyBindGen Edit question
Assignee:
No assignee Edit question
Solved by:
Stefan Stiene
Solved:
Last query:
Last reply:
Revision history for this message
Gustavo Carneiro (gjc) said :
#1

Choose caller_owns_return=True and also reference_existing_object=True (new in pybindgen 0.13). Although this produces suboptimal extension: if the python programmer tries to use the object when it has already been deleted in the C++ side => kaboom. But it works if you're careful.

Revision history for this message
Stefan Stiene (sstiene) said :
#2

Hi,
I have tried pybindgen 0.13 but I get stuck.
Now the generated code looks like this:

if (!(self->flags&PYBINDGEN_WRAPPER_FLAG_OBJECT_NOT_OWNED)) {
        delete tmp;
}

However if I debug my wrapper code
self->flags is PYBINDGEN_WRAPPER_FLAG_NONE

the object is deleted and it crashes.
My pybindgen code is:

cls.add_method('getFoo', retval('Foo*', caller_owns_return = True, reference_existing_object = True), [], is_virtual = True)

Thanks for your help
stefan

Revision history for this message
Gustavo Carneiro (gjc) said :
#3

Sorry, I mixed up :P

You should use only reference_existing_object=True, and omit caller_owns_return.

If in doubt, check the unit tests, tests/foo.h and tests/foomodulegen.py.

Revision history for this message
Stefan Stiene (sstiene) said :
#4

This solved it.
Thanks for your answer