The problem is basically this, in python's gobject and gtk bindings. Assume we have a class that binds to a signal when constructed:
class ClipboardMonitor (object):
clip = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD)
The standard way is to disconnect the signal. This however needs to have a destructor-like method in your class, called explicitly by code which maintains your object. This is necessary, because otherwise you'll get circular dependency.
class ClipboardMonitor(object): [...] def __init__(self): self.clip = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD) self.signal_id = self.clip.connect("owner-change", self._clipboard_changed) def close(self): self.clip.disconnect(self.signal_id)
As you pointed out, you need weakrefs if you want to avoid explicite destroying. I would write a weak callback factory, like:
import weakref class CallbackWrapper(object): def __init__(self, sender, callback): self.weak_obj = weakref.ref(callback.im_self) self.weak_fun = weakref.ref(callback.im_func) self.sender = sender self.handle = None def __call__(self, *things): obj = self.weak_obj() fun = self.weak_fun() if obj is not None and fun is not None: return fun(obj, *things) elif self.handle is not None: self.sender.disconnect(self.handle) self.handle = None self.sender = None def weak_connect(sender, signal, callback): wrapper = CallbackWrapper(sender, callback) wrapper.handle = sender.connect(signal, wrapper) return wrapper
(this is a proof of concept code, works for me -- you should probably adapt this piece to your needs). Few notes:
weakref.ref(obj.method)will destroy the bound method object instantly after creating a weakref. I didn't check whether it is needed to store a weakref to the function too... I guess if your code is static, you probably can avoid that.