]> Migrating to GDBus
Conceptual differences The central concepts of D-Bus are modelled in a very similar way in dbus-glib and GDBus. Both have objects representing connections, proxies and method invocations. But there are some important differences: dbus-glib uses the libdbus reference implementation, GDBus doesn't. Instead, it relies on GIO streams as transport layer, and has its own implementation for the D-Bus connection setup and authentication. Apart from using streams as transport, avoiding libdbus also lets GDBus avoid some thorny multithreading issues. dbus-glib uses the GObject type system for method arguments and return values, including a homegrown container specialization mechanism. GDBus relies on the #GVariant type system which is explicitly designed to match D-Bus types. dbus-glib models only D-Bus interfaces and does not provide any types for objects. GDBus models both D-Bus interfaces (via the #GDBusInterface, #GDBusProxy and #GDBusInterfaceSkeleton types) and objects (via the #GDBusObject, #GDBusObjectSkeleton and #GDBusObjectProxy types). GDBus includes native support for the org.freedesktop.DBus.Properties (via the #GDBusProxy type) and org.freedesktop.DBus.ObjectManager D-Bus interfaces, dbus-glib doesn't. The typical way to export an object in dbus-glib involves generating glue code from XML introspection data using dbus-binding-tool. GDBus provides a similar tool called gdbus-codegen that can also generate Docbook D-Bus interface documentation. dbus-glib doesn't provide any convenience API for owning and watching bus names, GDBus provides the g_bus_own_name() and g_bus_watch_name() family of convenience functions. GDBus provides API to parse, generate and work with Introspection XML, dbus-glib doesn't. GTestDBus provides API to create isolated unit tests GDBus Test Scaffolding.
API comparison dbus-glib APIs and their GDBus counterparts dbus-glibGDBus#DBusGConnection#GDBusConnection#DBusGProxy#GDBusProxy, #GDBusInterface - also see #GDBusObjectProxy#DBusGObject#GDBusInterfaceSkeleton, #GDBusInterface - also see #GDBusObjectSkeleton#DBusGMethodInvocation#GDBusMethodInvocationdbus_g_bus_get()g_bus_get_sync(), also see g_bus_get()dbus_g_proxy_new_for_name()g_dbus_proxy_new_sync() and g_dbus_proxy_new_for_bus_sync(), also see g_dbus_proxy_new()dbus_g_proxy_add_signal()not needed, use the generic #GDBusProxy::g-signaldbus_g_proxy_connect_signal()use g_signal_connect() with #GDBusProxy::g-signaldbus_g_connection_register_g_object()g_dbus_connection_register_object() - also see g_dbus_object_manager_server_export()dbus_g_connection_unregister_g_object()g_dbus_connection_unregister_object() - also see g_dbus_object_manager_server_unexport()dbus_g_object_type_install_info()introspection data is installed while registering an object, see g_dbus_connection_register_object()dbus_g_proxy_begin_call()g_dbus_proxy_call()dbus_g_proxy_end_call()g_dbus_proxy_call_finish()dbus_g_proxy_call()g_dbus_proxy_call_sync()dbus_g_error_domain_register()g_dbus_error_register_error_domain()dbus_g_error_has_name()no direct equivalent, see g_dbus_error_get_remote_error()dbus_g_method_return()g_dbus_method_invocation_return_value()dbus_g_method_return_error()g_dbus_method_invocation_return_error() and variantsdbus_g_method_get_sender()g_dbus_method_invocation_get_sender()
Owning bus names Using dbus-glib, you typically call RequestName manually to own a name, like in the following excerpt: message); g_error_free (error); } else { g_warning ("Failed to acquire %s", NAME_TO_CLAIM); } goto out; } if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { if (error != NULL) { g_warning ("Failed to acquire %s: %s", NAME_TO_CLAIM, error->message); g_error_free (error); } else { g_warning ("Failed to acquire %s", NAME_TO_CLAIM); } exit (1); } dbus_g_proxy_add_signal (system_bus_proxy, "NameLost", G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal (system_bus_proxy, "NameLost", G_CALLBACK (on_name_lost), NULL, NULL); /* further setup ... */ ]]> While you can do things this way with GDBus too, using g_dbus_proxy_call_sync(), it is much nicer to use the high-level API for this: Note that g_bus_own_name() works asynchronously and requires you to enter your mainloop to await the on_name_aquired() callback. Also note that in order to avoid race conditions (e.g. when your service is activated by a method call), you have to export your manager object before acquiring the name. The on_bus_acquired() callback is the right place to do such preparations.
Creating proxies for well-known names dbus-glib lets you create proxy objects for well-known names, like the following example: For a #DBusGProxy constructed like this, method calls will be sent to the current owner of the name, and that owner can change over time. The same can be achieved with #GDBusProxy: For an added layer of safety, you can specify what D-Bus interface the proxy is expected to conform to by using the #GDBusInterfaceInfo type. Additionally, #GDBusProxy loads, caches and tracks changes to the D-Bus properties on the remote object. It also sets up match rules so D-Bus signals from the remote object are delivered locally. The #GDBusProxy type normally isn't used directly - instead proxies subclassing #GDBusProxy generated by gdbus-codegen is used, see
Generating code and docs
Using gdbus-codegen dbus-glib comes with dbus-binding-tool, which can produce somewhat nice client- and server-side wrappers for a D-Bus interface. With GDBus, gdbus-codegen is used and like its counterpart, it also takes D-Bus Introspection XML as input: Example D-Bus Introspection XMLFIXME: MISSING XINCLUDE CONTENT: gdbus-example-objectmanager.xml If this XML is processed like this then two files generated-code.h and generated-code.c are generated. Additionally, two XML files generated-docs-org.gtk.GDBus.Example.ObjectManager.Animal and generated-docs-org.gtk.GDBus.Example.ObjectManager.Cat with Docbook XML are generated. For an example of what the docs look like see the Animal D-Bus interface documentation. and the Cat D-Bus interface documentation. While the contents of generated-code.h and generated-code.c are best described by the gdbus-codegen manual page, brief examples of how this generated code can be used can be found in and . Additionally, since the generated code has 100% gtk-doc coverage, see #ExampleAnimal, #ExampleCat, #ExampleObject and #ExampleObjectManagerClient pages for documentation. Server-side application using generated codeFIXME: MISSING XINCLUDE CONTENT: gdbus-example-objectmanager-server.c Client-side application using generated codeFIXME: MISSING XINCLUDE CONTENT: gdbus-example-objectmanager-client.c
FIXME: MISSING XINCLUDE CONTENT: objectmanager-gen-org.gtk.GDBus.Example.ObjectManager.Animal.xml FIXME: MISSING XINCLUDE CONTENT: objectmanager-gen-org.gtk.GDBus.Example.ObjectManager.Cat.xml FIXME: MISSING XINCLUDE CONTENT: ExampleAnimal.xml FIXME: MISSING XINCLUDE CONTENT: ExampleCat.xml FIXME: MISSING XINCLUDE CONTENT: ExampleObject.xml FIXME: MISSING XINCLUDE CONTENT: ExampleObjectManagerClient.xml