Search code examples
pythonpygtkglib

Why do io_add_watch() callbacks receive the wrong IOChannel object?


As far as I can tell from the available docs, GLib.io_add_watch() is supposed to register a function to be called when a condition occurs on an IOChannel, and the callback function is supposed to receive said IOChannel as its first argument. Great, except that it doesn't. GLib is passing a completely different IOChannel object to the callback. Why?

To put it another way, why does this code produce an AssertionError?

#!/usr/bin/env python3

import gi
from gi.repository import GLib

_, _, fd, _ = GLib.spawn_async(['/bin/echo', 'hello'], standard_output=True)

channel = GLib.IOChannel.unix_new(fd)

def on_read(callback_channel, condition):
    assert callback_channel is channel

GLib.io_add_watch(channel, GLib.PRIORITY_DEFAULT, GLib.IO_IN, on_read)

GLib.MainLoop().run()

Solution

  • The IOChannel is a GBoxed struct, not a GObject. It has no identity and is passed by copy. The one you receive in the call back is equivalent to the one you gave but they aren't the same object nor will all their fields have the same value.