Search code examples
cglib

How do I instantiate a GValue in C?


I'm converting some C code from using GVariant to GValue as it seems to fit what I'm doing with it better. With GVariant, I could easily instantiate them using one of the many constructors listed in the documentation, e.g. g_variant_new_string (), but in the GValue documentation I don't see any constructors listed.

I tried doing something like this:

/* Instantiate the GValue structure. */
GValue *value = g_new (GValue, 1);
/* Initialise it to a string. */
g_value_init (value, G_TYPE_STRING);
/* Set it to some data. */
g_value_take_string (value, data);

However, this fails on g_value_init (value, G_TYPE_STRING) with the following:

GLib-GObject-CRITICAL **: 17:29:30.782: ../gobject/gvalue.c:99: cannot initialize GValue with type 'gchararray', the value has already been initialized as '(null)'

I never intentionally initialised it to "(null)", so clearly I'm doing something wrong.

I also tried using GValue *value = malloc (sizeof (GValue)), but this results in a segmentation fault when I use it in g_value_init ().

Another thing I tried was GValue *value = g_object_new (G_TYPE_VALUE, NULL), but this fails with the following:

GLib-GObject-CRITICAL **: 17:49:23.518: g_object_new_with_properties: assertion 'G_TYPE_IS_OBJECT (object_type)' failed

How do I properly instantiate a GValue in C?


Solution

  • It turns out the answer is very simple: GValue must be zero-filled in order to be initialised using g_value_init (). The easiest way to achieve this is to use g_new0 () instead of g_new (). So, to fix the above example, something like this would work:

    /* Instantiate the GValue structure. */
    GValue *value = g_new0 (GValue, 1);
    /* Initialise it to a string. */
    g_value_init (value, G_TYPE_STRING);
    /* Set it to some data. */
    g_value_take_string (value, data);
    

    The only difference is that it's using g_new0 () instead of g_new ().