Search code examples
pythondbusgio

Registering an Object on DBus using pythons Gio-Bindings


I'm working on a Python-Clone of an existing C-Project. The C-Project Connects to a custom DBus and offers a Object there for getting Callbacks.

I tried to replicate this using Python with code that basically boils down to:

def vtable_method_call_cb(connection, sender, object_path, interface_name, method_name, parameters, invocation, user_data):
    print('vtable_method_call_cb: %s' % method_name)

connection = Gio.DBusConnection.new_for_address_sync(
    "unix:abstract=gstswitch",
    Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT,
    None,
    None)

node_info = Gio.DBusNodeInfo.new_for_xml(introspection_xml)

vtable = Gio.DBusInterfaceVTable()
vtable.method_call(vtable_method_call_cb)
vtable.get_property(None)
vtable.set_property(None)

connection.register_object(
    "/info/duzy/gst/switch/SwitchUI",
    node_info.interfaces[0],
    vtable,
    None,
    None)

The code fails when creating the vtable at the vtable.method_call call (but get_property fails, too, when I comment one call out) the following log/traceback:

** (process:18062): WARNING **: Field method_call: Interface type 2 should have is_pointer set
Traceback (most recent call last):
  File "moo.py", line 69, in <module>
    vtable.method_call(vtable_method_call_cb)
RuntimeError: unable to get the value

I was not able to find code using register_object() in python, so I'm unsure if this part of Gio should be usable or if it's just not complete.


Solution

  • This certainly not what you'll want to hear, but you have hit a 4 year old bug in the GDBus Python bindings that makes it impossible to register objects on the bus. A patch had been proposed quite some time ago, but every time it looked like it was actually going to land, some GNOME developer found something he/she did not like something about it, a new patch was proposed... and nothing happend for most of the next year. This cycle has already happend 3 times and I do not know if there is much hope that it will be broken anytime soon...

    Basically the GNOME developers themselves more or less suggested that people use dbus-python until this issue is finally fixed, so I guess you should be heading here instead. :-/

    BTW: I think you source code is wrong (aside from the fact that it won't work either way). To create the VTable you would actually be written something like this, I think:

    vtable = Gio.DBusInterfaceVTable()
    vtable.method_call  = vtable_method_call_cb
    vtable.get_property = None
    vtable.set_property = None
    

    But since the bindings are broken you are just trading an exception with an abort() here... :-(

    If the patch actually makes it into python-gi in the current form the vtable would be dumped entirely (YEAH!) and connection.register_object call would become:

    connection.register_object_with_closures(
        "/info/duzy/gst/switch/SwitchUI",
        node_info.interfaces[0],
        vtable_method_call_cb, # vtable.method_call
        None,                  # vtable.get_property
        None)                  # vtable.set_property
    

    Update

    It appears this has now finally been fixed! You can now export object using g_dbus_connection_register_object_with_closures:

    def vtable_method_call_cb(connection, sender, object_path, interface_name, method_name, parameters, invocation, user_data):
        print('vtable_method_call_cb: %s' % method_name)
    
    connection = Gio.DBusConnection.new_for_address_sync(
        "unix:abstract=gstswitch",
        Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT,
        None,
        None)
    
    node_info = Gio.DBusNodeInfo.new_for_xml(introspection_xml)
    
    connection.register_object(
        "/info/duzy/gst/switch/SwitchUI",
        node_info.interfaces[0],
        vtable_method_call_cb,
        None,
        None)