On Sunday 04 September 2005 7:51 pm, David Boddie wrote:
> On Thursday 01 September 2005 09:10, Phil Thompson wrote:
> > > I'm not sure where the changes have occurred but, without applying any
> > > patches of my own, I now find that:
> > >
> > > * None of my KPart plugins work any more - the receivers for the
> > > KActions I set up are never called. I'm still chasing this bug but
> > > it seems that, unlike C++ slots, Python functions/methods are never
> > > called. It seems that the Python slot is somehow transferred out of
> > > existance by the KAction because, if I assign the method to an instance
> > > variable (keeping a copy around), the slot is called when the action is
> > > activated.
>
> Just to provide an update - but still no test script, unfortunately - I've
> subsequently discovered that keeping another reference to the slot is also
> not sufficient to get the plugin to work. I've since discovered another,
> possibly more reliable, workaround is to keep a reference to the plugin in
> the object that creates it (an instance of a KLibFactory subclass):
>
> class FactoryClass(KLibFactory):
>
> instance = None
>
> def __init__(self, parent = None, name = None):
>
> KLibFactory.__init__(self, parent, name)
> if FactoryClass.instance is None:
> FactoryClass.instance = KInstance("Highlighter")
>
> def createObject(self, parent=None, name=None, class_name="QObject",
> args=None):
> if args is None:
> args = []
>
> self.plugin = Highlighter(parent, name)
> self.emit(SIGNAL("objectCreated(QObject)"), (self.plugin,))
> return self.plugin
>
> > Got a test script? When a connection is made to a Python slot the
> > reference count of the slot is not increased (never has been). The
> > current garbage collection is much more "correct" than in previous
> > versions, so (perhaps) it's exposed an existing bug rather than created a
> > new one. Have you been using previous snapshots, or were you using
> > 4.2.1/3.14.1?
>
> I began to suspect that something is happening to the Python object when it
> is returned by the createObject() method. The code for the createObject()
> function in sipKLibFactory uses another function to call the relevant
> Python method, if it has been implemented:
>
> QObject * sipVH_kdecore_29(sip_gilstate_t sipGILState, PyObject *sipMethod,
> QObject *a0, const char *a1, const char *a2, const QStringList
> &a3) {
> QObject * sipRes = 0;
> PyObject *sipResObj = sipCallMethod(0, sipMethod, "MssO", a0,
> sipClass_QObject, a1, a2, const_cast<QStringList*>(&a3),
> sipClass_QStringList);
>
> if (!sipResObj || sipParseResult(0, sipMethod, sipResObj, "L",
> sipForceConvertTo_QObject, &sipRes) < 0)
> PyErr_Print();
>
> Py_XDECREF(sipResObj);
> Py_DECREF(sipMethod);
>
> SIP_RELEASE_GIL(sipGILState)
>
> return sipRes;
> }
>
> My question is: doesn't the call to Py_XDECREF(sipResObj) cause problems
> for Python objects that have gone out of scope? For example, if I don't
> store the plugin in the factory and use
>
> plugin = Highlighter(parent, name)
> self.emit(SIGNAL("objectCreated(QObject)"), (plugin,))
> return plugin
>
> instead, it seems that it is collected. To test this, I implemented a
> __del__ method in my Highlighter class to print a message when this occurs
> and, sure enough, it appeared just after the plugin was created. Keeping a
> reference to the plugin means that I never see this message. :-/
It looks like the KLibFactory::createObject() SIP specification is missing
a /Factory/ annotation. This cause the generated virtual handler to transfer
ownership to C++ before calling Py_XDECREF(sipResObj) so the C++ dtor doesn't
get called when sipResObj is garbage collected.
If you are reimplementing createObject() then (I think) you will need to do
the same...
sip.transferto(plugin, None)
return plugin
Phil
_______________________________________________
PyKDE mailing list [email protected]
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde