[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