>    Using sip.transfer(), as Phil suggested, keeps the destructor of my
> object created by clone() from being destroyed.   However, my object
> is still not useable as it can't find the Python implemented methods
> when it is called from C++ after return of clone.
>
>    Poking around, I found that sipFunctionBase::sipPySelf data member
> has gotten reset to zero.   Using SIP trace and adding some printing
> in the generated sipFunctionBase.cpp file by hand, the trace back
> is...
>
>
> FunctionBase * sipFunctionBase::clone() const (this=0x083c9d90)
>   sipPySelf = 0x419c623c
> python.clone
> init_FunctionBase  sipSelf = 0x419c629c
> sipFunctionBase::sipFunctionBase(const FunctionBase&) (this=0x08406528)
>   sipPySelf = 0
>   sipCpp = 0x8406528
> python.copy
> dealloc_FunctionBase  sipSelf = 0x419c629c
>   sipIsSimple not
> const std::vector<double>& sipFunctionBase::getParameters()
> (this=0x08406528)
>   sipPySelf = 0
>
> Note
>
> - sipFunctionBase::clone() finds the Python member function and calls
>   it.  Looks ok
>
> - The sipFunctionBase copy constructor gets called followed by Python
>   __init__ method.  Looks ok
>
> - on return, dealloc_FunctionBase is called with argument of the newly
>   created instance.   It appears that sipPySelf is then set to zero!
>
> - The very first call to a member function shows indeed that the member
>   sipPySelf is a null pointer.
>
> Any ideas, suggestions?

sipPySelf is the pointer to the Python instance object. It is reset to 0
to show that it has been garbage collected. Unfortunately, as you have
found, it means the Python virtual reimplementations can no longer work.
There is a slight difference between the Python sip.transfer() and the C++
sipTransfer(). The latter creates an extra reference to the Python object
to prevent to being garbage collected - the former doesn't because the
intent was to completely divorce the Python and C++ objects. You want the
behaviour of sipTransfer() rather than sip.transfer().

There are two solutions...

I add an optional second argument to sip.transfer() that causes it to
behave like sipTransfer() - I will do this anyway in the next few days.

You use sipTransfer() - but you must call it before the Python object is
garbage collected, ie. you must provide %VirtualCatcherCode for clone().
This is probably what you want to do if you want to make life as easy as
possible for your users writing the Python reimplementations.

Phil

_______________________________________________
PyKDE mailing list    [email protected]
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde

Reply via email to