introspecting tp-glib and converting DBus-GLib GValues to GVariants

Telepathy is a modular framework. At the very heart of Telepathy there is a specification that describes how the various connection managers, clients and other components interact with each other. The specification is written in terms of a set of D-Bus APIs.

Telepathy takes full advantage of what’s provided by D-Bus, which is why you see so many different interfaces in the specification (one day I’ll write more about this), but one thing it makes frequent use of is variant types and specifically string->variant maps (known in D-Bus parlance as a{sv} maps).

a{sv} maps are used by the DBus.Properties.GetAll() method, to return all of the properties in an interface (which are all of different types), but in Telepathy they’re used more generically with namespaced properties to make requests for communication channels and collate information. The types are specified by the key names.

Telepathy-GLib exposes these maps as GHashTables of element type string->GValue, which actually works quite well in C. Telepathy-GLib registers specific GTypes with GLib via DBus-GLib and we have generic utility functions to unpack the GValues into native C types. For simple types, this also works really well in the bindings. For simple types (int, string, boolean, etc.) GJS converts the GValue values in our map into native JS values and things are pretty neat. Unfortunately this does not work for complex, container types (e.g. sa{sv}as); GLib doesn’t provide enough API to query the complete type information of the GValue’s contents, thus it’s not possible to introspect.

The GLib solution to this problem is GVariant, a way to store values that keeps all of the type information in an easily accessible way. If tp-glib exposed a{sv} maps as string->GVariant, we would easily be able to unpack the complete type in GJS or PyGI. GDBus uses GVariant for passing around types, but porting tp-glib to GDBus would take a lot of effort and radically break the API and ABI, so just isn’t feasible at this stage.

But there is a solution! Unsurprisingly, DBus-GLib has the information to recursively unpack a GValue registered with itself, it requires this in order to marshal those GValues into a D-Bus message, but it also exposes this API so we can use it for our own ends. Thus it becomes possible to convert these GValues to GVariants! In fact here is some sample code (Telepathy-GLib is not strictly required, it’s only being used here to provide test cases). I’m hoping this utility can be provided as part of DBus-GLib and then used to provide alternative API for tp-glib that can be exposed to the bindings.

To complete the circle, I wrote GVariant unpacking for GJS, but it needs reworking to only unpack when explicitly requested instead of implicitly always.

Update: bug #28715 provides a proposed patch to dbus-glib.

Author: Danielle

Danielle is an Australian software engineer, computer scientist and feminist. She doesn't really work on GNOME any more (sadly). Opinions and writing are solely her own and so not represent her employer, the GNOME Foundation, or anyone else but herself.

Leave a Reply

Your email address will not be published. Required fields are marked *

Creative Commons Attribution-ShareAlike 2.5 Australia
This work by Danielle Madeley is licensed under a Creative Commons Attribution-ShareAlike 2.5 Australia.