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