Thursday, September 22, 2011

New D-Bus features in GLib 2.30

For the upcoming GLib 2.30 release, there's a couple of new features to make it even easier to use D-Bus.

C Code Generator

GLib 2.30 ships with a command called gdbus-codegen(1) which can be used to generate C code. The command is similar in spirit to the dbus-binding-tool(1) command but it targets the D-Bus implementation added to GLib 2.26 (often informally referred to as GDBus). The command's manual page and migration documentation is the authoritative source of documentation, but from a 50,000 feet view what the tool does is simply to map a D-Bus interface (described by XML) to a couple of GObject-based types (including all D-Bus methods, signals and properties). It of course supports the PropertiesChanged signal added in D-Bus spec 0.14.

Even though the tool is targeting C programmers (most higher-level languages are a lot more dynamic than C so objects can be exported via e.g. language meta-data such as annotations), it's useful to note that the generated code is 100% annotated so it can be used from e.g. JavaScript through GObject Introspection - for example the GNOME Documents application (written in JavaScript) is consuming the GNOME Online Accounts client-library which is 99% generated by the gdbus-codegen(1) command.

In addition to just generating code, the gdbus-codegen(1) command can also generate very nice Docbook documentation (example 1, example 2) for D-Bus interfaces - in this respect it's useful even for non-GNOME applications in the same way a lot of libraries like libblkid and libudev are already using gtk-doc for their C library documentation.

Object Manager

Another part of GLib 2.30 is support for the org.freedesktop.DBus.ObjectManager D-Bus interface - in fact, the implementation in GLib, that is, the newly added GDBusObject{Proxy,Skeleton}and GDBusObjectManager{Client,Server} types, is actually what drove me to propose this as a standard interface instead of just doing a GLib-only thing (with shoutouts to my homeboys smcv and walters for excellent review and feedback).

In a nutshell, the org.freedesktop.DBus.ObjectManager interface is basically a formalization of what each and every non-trivial D-Bus service is already doing: offering some kind of GetAll() method (to return all objects) and signals ::Foo{Added,Removed} (to convey changes) on its Manager interface in its own special way (example 1, example 2). It first sounds weird to standardize such a simple thing as object enumeration and change signals but if you think about all the possible edge cases and race-conditions then using a well-tested implementation just makes everything so much easier. Additionally, with the way the interface is defined and the newly added path_namespace match rule, two method invocations and a single round-trip is all it takes for a client to grab the state from the service - this is a huge win compared to existing services that typically first retrieve a list of object paths and then gets properties for each object path (and only if you are lucky it does the latter in parallel).

When combined with the gdbus-codegen(1) command (which can also generate specialized GDBusObject types for use with GDBusObjectManager) you can start writing service-specific code right away and not worry about horrible implementation details like marshaling, too many round trips or race conditions. It just works out of the box as you'd expect it to.