GNOME Bugzilla – Bug 784433
gdbus-codegen with variant type parameters result in nested variant
Last modified: 2017-07-04 15:04:11 UTC
gdbus-codegen uses g_dbus_gvariant_to_gvalue on the child of the variant iter. This is used to convert the child to paramv. For variant type child g_dbus_gvariant_to_gvalue behaves as if use_gvariant was set: If the GVaraint is of type variant, will set GValue to the pointer to the provided variant, not the variant this variant contains. I would expect this GValue to be set to the "inside" variant. The documentation doesn't explain this properly. Exmaple: var = GVariant of type "v" containing a GVaraint of type "b" g_dbus_gvariant_to_gvalue (var, &val); val = GValue holding GVaraint var I would expect: val = GValue holding GVariant of type "b" This behaviour isn't clear for g_dbus_gvariant_to_gvalue, nor is it explained for gdbus-codegen generated signals. If this is the intended behaviour, please add documentation for both g_dbus_gvariant_to_gvalue and gdbus-codegen generated signals.
For g_dbus_gvariant_to_gvalue is it understandable that the container variant is placed into the gvalue instead of the contained variant as the following types are kept as variant when they are placed into a gvalue: G_VARIANT_CLASS_HANDLE, G_VARIANT_CLASS_MAYBE, G_VARIANT_CLASS_TUPLE, G_VARIANT_CLASS_DICT_ENTRY as well as array typed variants. To be to make g_dbus_gvalue_to_gvariant work properly as each others opposite G_VARIANT_CLASS_VARIANT needs to be contained within a GVariant as well. It would be good to make that clear in the docs. For gdbus-codegen is isn't obvious to the user g_dbus_gvariant_to_gvalue is used, the user can't use g_dbus_gvalue_to_gvariant on it, so there is no need for the GVariant to be contained within a GVariant. I understand that implementation wise it is good to use g_dbus_gvariant_to_gvalue and not write another (or use an explicit gvariant check). Also changing the behaviour now can break existing code. It would be good to point to g_dbus_gvariant_to_gvalue in the docs to make this clear.
(In reply to Peter de Ridder from comment #0) > For variant type child g_dbus_gvariant_to_gvalue behaves as if use_gvariant > was set: > If the GVaraint is of type variant, will set GValue to the pointer to the > provided variant, not the variant this variant contains. > I would expect this GValue to be set to the "inside" variant. Why would you expect that? How many levels of unboxing would you expect the generated code to do? If the generated code were to do any unboxing, then the signal emissions of GVariants with types b, vb, vvb and vvvb would all be identical. That’s not correct — if the programmer has passed a boxed type into a signal emission, they should expect that boxed type to be propagated to the signal handlers, not arbitrarily unboxed. Also, as you noted, changing this behaviour now (even if it made sense to change) would be an API break. > If this is the intended behaviour, please add documentation for both > g_dbus_gvariant_to_gvalue and gdbus-codegen generated signals. I’ll attach a patch which clarifies the g_dbus_gvariant_to_gvalue() documentation a little.
Created attachment 354871 [details] [review] gdbusutils: Add an example to g_dbus_gvariant_to_gvalue() docs Clarify that GVariants of type v are not magically unboxed. Signed-off-by: Philip Withnall <withnall@endlessm.com>
(In reply to Philip Withnall from comment #2) > (In reply to Peter de Ridder from comment #0) > > For variant type child g_dbus_gvariant_to_gvalue behaves as if use_gvariant > > was set: > > If the GVaraint is of type variant, will set GValue to the pointer to the > > provided variant, not the variant this variant contains. > > I would expect this GValue to be set to the "inside" variant. > > Why would you expect that? How many levels of unboxing would you expect the > generated code to do? If the generated code were to do any unboxing, then > the signal emissions of GVariants with types b, vb, vvb and vvvb would all > be identical. That’s not correct — if the programmer has passed a boxed > type into a signal emission, they should expect that boxed type to be > propagated to the signal handlers, not arbitrarily unboxed. I don't mean recursive unboxing. I this case I have a method with (svu) with the following example values: plugin: "name" value : variant true handle: 2 The signal of this method gives me: gchar *plugin = "name" GVariant *value = variant variant true gulong handle = 2 value is the iter variant, where I would have expected* it to be the variant containing the value true. *(at the time I wrote the original post) If I would use g_variant_get(parameters, "(svu)", &plugin, &value, &handle) this would give me: gchar *plugin = "name" GVariant *value = variant true gulong handle = 2 That is where I got confused. > Also, as you noted, changing this behaviour now (even if it made sense to > change) would be an API break. > > > If this is the intended behaviour, please add documentation for both > > g_dbus_gvariant_to_gvalue and gdbus-codegen generated signals. > > I’ll attach a patch which clarifies the g_dbus_gvariant_to_gvalue() > documentation a little. Thank you, that helps to understand to handle variant types differently.
Attachment 354871 [details] pushed as 5a8b02c - gdbusutils: Add an example to g_dbus_gvariant_to_gvalue() docs