[PyKDE] ANN: New Releases of PyQt, PyKDE, SIP and QScintilla

David Boddie david at boddie.org.uk
Sun Sep 4 19:51:38 BST 2005


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. :-/

David




More information about the PyQt mailing list