I am trying to iterate over a GtkVariant which is of the format “aa{uv}”. The top level structure is a list where each of the elements in that list is a dictionary.
The string representing that structure get’s successfully parsed (using g_variant_parse()
). However, I can’t seem to get the element in the array working. I am using the following code:
GVariant *variant, *elem = NULL;
GVariantIter iter;
GError *error = NULL;
variant = g_variant_parse(G_VARIANT_TYPE("aa{uv}"), data,
data + strlen(data), NULL, &error);
if (!variant) {
warning("Failed to parse data: %s", error->message);
g_error_free(error);
return;
}
g_variant_ref_sink(variant);
printf("data type: %s\n", g_variant_get_type_string(variant));
g_variant_iter_init(&iter, variant);
while (g_variant_iter_next(&iter, "a{uv}", &elem)) {
printf("%p %s\n", elem, g_variant_get_type_string(elem));
g_variant_unref(elem);
}
The above code generates a abort (as a result of a call to g_error()
) in the call to g_variant_get_type_string(elem)
with the following output:
data type: aa{uv}
**
GLib:ERROR:…/…/…/…/glib/gvarianttypeinfo.c:163:g_variant_type_info_check: assertion failed: (info->alignment == 0 || info->alignment == 1 || info->alignment == 3 || info->alignment == 7)
Can someone help me understand where I am going wrong?
Thank you
pwithnall
(Philip Withnall)
March 18, 2019, 5:53pm
2
Can you give a minimal reproducer which includes the allocation and instantiation of data
please?
voidtrance:
GVariant *variant, *elem = NULL; GVariantIter iter; GError *error = NULL; variant = g_variant_parse(G_VARIANT_TYPE(“aa{uv}”), data, data + strlen(data), NULL, &error); if (!variant) { warning(“Failed to parse data: %s”, error->message); g_error_free(error); return; } g_variant_ref_sink(variant); printf(“data type: %s\n”, g_variant_get_type_string(variant)); g_variant_iter_init(&iter, variant); while (g_variant_iter_next(&iter, “a{uv}”, &elem)) { printf(“%p %s\n”, elem, g_variant_get_type_string(elem)); g_variant_unref(elem); }
Here you go:
#include <glib.h>
#include <stdio.h>
int main(void) {
const gchar data[] = "[{uint32 2959077576: <{'a': <(uint32 1, uint32 71, 'test1')>, 'b': <[{uint32 580176270: <{'c': <(uint32 0, uint32 3, 'test2')>, 'b': <@aa{uv} []>}>}]>}>}]";
GVariant *variant, *elem = NULL;
GVariantIter iter;
GError *error = NULL;
variant = g_variant_parse(G_VARIANT_TYPE("aa{uv}"), data,
data + strlen(data), NULL, &error);
if (!variant) {
g_warning("Failed to parse data: %s", error->message);
g_error_free(error);
return -1;
}
g_variant_ref_sink(variant);
printf("data type: %s\n", g_variant_get_type_string(variant));
g_variant_iter_init(&iter, variant);
while (g_variant_iter_next(&iter, "a{uv}", &elem)) {
printf("%p %s\n", elem, g_variant_get_type_string(elem));
g_variant_unref(elem);
}
return 0;
}
pwithnall
(Philip Withnall)
March 18, 2019, 6:18pm
4
I have to run now, but try ensuring that data
is aligned on an 8-byte boundary. You can use malloc()
to do this.
Philip
Changing the declaration of data to:
const gchar data[] __attribute__((aligned(8))) = "[{uint32 2959077576: <{'a': <(uint32 1, uint32 71, 'test1')>, 'b': <[{uint32 580176270: <{'c': <(uint32 0, uint32 3, 'test2')>, 'b': <@aa{uv} []>}>}]>}>}]";
and aligning it on an 8 byte boundary doesn’t work.
chergert
(Christian Hergert)
March 18, 2019, 8:36pm
6
If you just want the value as a GVariant
, you might try g_variant_iter_next_value()
instead of g_variant_iter_next()
.
So, what the difference? From the documentation, it seem that both calls set the elem
GVariant to the same thing.
pwithnall
(Philip Withnall)
March 19, 2019, 8:55am
8
Having played with it a little this morning, this looks like it’s potentially a bug in GVariant
. Would you mind filing a bug in GitLab about it please, attaching your minimal reproducer, and someone can take a look? Otherwise it’ll get lost on Discourse. Thanks.
system
(system)
Closed
March 24, 2019, 4:03pm
10
This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.