glib2/gdbus - arrays and g_variant_get() quirks

David Sommerseth dbus at lists.topphemmelig.net
Tue Oct 10 21:14:12 UTC 2017


On 10/10/17 17:53, Simon McVittie wrote:
> On Mon, 09 Oct 2017 at 23:35:38 +0200, David Sommerseth wrote:
[...snip...]
>> But I'm not really happy about the '(*)'.  So I change that to say:
>>
>>      g_variant_get(res, "(au)", &array);
> 
> You can't do this unless you change the type of 'array'. The format
> string "(*)" expects a GVariant * argument, but the format string
> "(au)" (or in fact "(aX)" for any X) expects a GVariantIter **.
> 
> See: https://developer.gnome.org/glib/stable/gvariant-format-strings.html
> 
> If you want both a GVariant * and type assertions, use "(@au)".
> 
> In general, g_variant_get() and g_variant_new() are designed for
> convenience, rather than maximum possible consistency - the thought is
> "if you have something that you know to be an array, clearly you are
> going to want to iterate over it".
> 
> g_variant_get() with format string "(*)" or "(@au)" is effectively a
> short-cut for calling g_variant_get_child_value() (and an assertion
> about the type, in the case of "(@au)".
> 
> g_variant_get() with format string "(au)" is effectively a short-cut
> for calling g_variant_get_child_value(), g_variant_iter_new() and
> g_variant_iter_init().

Ahh!  Now I see!  And yes, I understand I didn't think this through
enough using GVariant * with (au).  I switched to using GVariantIter,
and things got a lot more simple.  This explanation with the docs URL
was key to make me understand how to resolve it.

>> I do know that results from D-Bus are inside a "container", so the ()
>> encapsulation is needed.
> 
> This is a true fact about the GDBus API for D-Bus, but it is not a
> general fact about D-Bus. In generic D-Bus the hierarchy is:
> 
>     message
>         header
>             message type
>             object path
>             interface
>             etc.
>         body, consisting of 0-many times:
>             parameter
> 
> In the GDBus API, the representation for a message body happens to be a
> GVariant of type tuple, because that's a convenient way to encapsulate
> 0 or more GVariant>
> In other D-Bus APIs (like libdbus, and I think also sd-bus) there is no
> representation for a message body as separate from a message.

Aha ... Okay, this makes sense.  I was recommended to have a closer look
at sd-bus, but it wasn't easily available in RHEL7 outside the systemd
project source (not even API stable in systemd 219).  I did have a look
at libdbus, but felt the complexity and documentation was poorer
compared to glib2/gdbus.  Plus several developers recommended to stay
away from libdbus.

> "Container" is a jargon term in the D-Bus and GVariant data-type models -
> it means an array, a D-Bus struct or GVariant tuple (they're the same
> thing), a variant, a dict-entry or a GVariant "maybe" type - so it's
> best to avoid using that word with its generic meaning.

Right ... I was just missing the proper terminology word for this
context.  But thanks a lot for the enlightenment.  I appreciate all the
responses and educational feedback here immensely.


-- 
kind regards,

David Sommerseth


More information about the dbus mailing list