[PyQt] sip: how to make a python instance owned by C++ without using a parent

Mathias.Born at gmx.de Mathias.Born at gmx.de
Tue Aug 14 22:47:51 BST 2012


Thanks for the answer. However, it appears I've not made myself
clear enough.
I don't want the C++ wrapper to be owned by Python; surely, I
can achieve that with "sipTransferTo". But nothing is done about the
Python part. When I delete the wrapper in C++, the Python part it wraps
stays alive, because its reference count is not touched. (No parent!)
I have to manually, explicitely decrease the reference count to get
rid of it. I'm not complaining. I get this Python object from a Python
function, so I have to take care of it.

However, the sip module already contains some code that essentially
already would do what I want:

======================== siplib.c ===================================
void sip_api_common_dtor(sipSimpleWrapper *sipSelf)
{
    if (sipSelf != NULL && sipInterpreter != NULL)
    {
        PyObject *xtype, *xvalue, *xtb;

        SIP_BLOCK_THREADS

        /* We may be tidying up after an exception so preserve it. */
        PyErr_Fetch(&xtype, &xvalue, &xtb);
        callPyDtor(sipSelf);
        PyErr_Restore(xtype, xvalue, xtb);

        sipOMRemoveObject(&cppPyMap, sipSelf);

        /* This no longer points to anything useful. */
        clear_access_func(sipSelf);

        /*
         * If C/C++ has a reference (and therefore no parent) then remove it.
         * Otherwise remove the object from any parent.
         */
        if (sipCppHasRef(sipSelf))
        {
            sipResetCppHasRef(sipSelf);
            Py_DECREF(sipSelf);
        }
        else if (PyObject_TypeCheck((PyObject *)sipSelf, (PyTypeObject *)&sipWrapper_Type))
            removeFromParent((sipWrapper *)sipSelf);

        SIP_UNBLOCK_THREADS
    }
}
=====================================================================

What about:

        if (sipCppHasRef(sipSelf))
        {
            sipResetCppHasRef(sipSelf);
            Py_DECREF(sipSelf);
        }

Is there an official way for my wrapper to have the "SIP_CPP_HAS_REF" flag set?
It would then automatically dispose its Python counterpart.

Best Regards,
Mathias Born



On 14.08.2012, 10:22:26 Phil Thompson wrote:
> On Mon, 13 Aug 2012 23:07:07 +0200, Mathias.Born at gmx.de wrote:
>> Hi,
>> 
>> I have a C++ class "Project", which I expose to Python
>> via sip.
>> In Python, I sub-class:
>> 
>> class Derived(Project):
>>       ...
>> 
>> In addition, there is a Python factory function which creates an
>> instance of "Derived" and returns it:
>> 
>> def f():
>>     return Derived(...)
>> 
>> I call this function from withing C++, and feed the return
>> value into "sipConvertToType", in order to create a wrapper
>> of type "Project", so I can call methods of the returned
>> "Derived" instance from within C++, using the wrapper.
>> 
>> Since the "Derived" instance is created by Python, it is
>> owned by Python.
>> Is there a way to transfer ownership to C++ without using any
>> additional objects? I want the Python part to stick to the
>> C++ wrapper until the latter is destroyed, at which point
>> the Python part should also be automatically disposed, without
>> any need to micro-manage the Python part myself.

> That will happen automatically anyway so long as Derived has a virtual
> dtor. The Python object will only ever be destroyed when its reference
> count reaches 0, irrespective of the state of the C++ instance.

>> In the sip sources, I can see a flag "SIP_CPP_HAS_REF" that
>> might just achieve that, but there appears to be no official
>> way to use it.

> To transfer ownership of a Python object to C++ (ie. to control whether
> the Python dealloc code calls the C++ dtor) use...

> http://www.riverbankcomputing.com/static/Docs/sip4/c_api.html#sipTransferTo

> Phil



More information about the PyQt mailing list