GNOME Bugzilla – Bug 110528
collecting value arrays is inconvenient
Last modified: 2011-02-18 16:07:08 UTC
It is possible to install properties with type "array of strings", but in order to use them in g_object_set(), one has to manually marshal a C string array into a GValueArray, which feels pretty unnatural. It would be much nicer to be able to write gchar *authors[] = { "Owen", "Tim", NULL }; g_object_set (obj, "authors", authors, ...); This could be solved easily enough for string arrays by introducing a new boxed type form them, but you have to add another boxed type whenever you need a new type-restricted value array, e.g. for a properties with type "array of integers" or "pair of doubles" (both of these can be declared with GValueArray), one would want to write gint ints[] = {1, 2, 3}; g_object_set (obj, "ints", 3, ints, "coords", 5.0, 1.5,...) So it would be nice if the type restrictions which can be declared in GParamSpecValueArray could somehow be used to parameterize the marshalling of the underlying value array. If that is too complicated, at least the addition of a GParamSpecStringArray should be considered, since that would be nice for GtkAboutDialog.
Here is the very minimum which allows to use C string arrays in a natural way in g_object_set(). It adds a new boxed type for gchar** using g_strdupv and g_strfreev for copy and free. The more general ideas above would still be nice.
Created attachment 15653 [details] [review] the patch
The nice thing about using the strdupv style string arrays is that it avoids the deadly array/length ordering debate of bug 50209... it also is very convenient for constant arrays in C programs or using the results of g_strsplit(). OTOH, having VALUE_ARRAY take a structure, STRING_ARRAY take a strdupv() style array, and then adding an INT_ARRAY in the future that takes a len/array pair seems like the path of madness. What do you think, Tim?
matthias, i don't see a way of solving array marshalling generically by guessing from the element_spec of a GParamSpecValueArray. what you're doing for strings here is a pure convenience hack, based on a specialised case of string pointer arrays (i.e. a NULL terminated array of pointers or NULL). this isn't going to work for other types as you demonstrated for intergers already, so a generic version would probably do things like force you to give the length for a string array as well (it'd support ordinary arrays of strings then, not just the specialised NULL-terminated case). that's mostly why gobject doesn't have such a thing already. for g_object_set() however, which is a pure C-convenince interface already, g_strdupv()-style properties provide a moderately convenient facility, so i think the implementatoin which amounts merely to another boxed type is justified. i'm not sure whether it's good to conflict with the g_string namespace though, looking at the other NULL-terminated string array functions we have in glib, g_strv_get_type() might be a suitable alternative. opinions, owen? in any case, the docs will need an example of how to use this type in object_set and object_get, so users know to NULL terminate their arrays, and know to use g_strfreev() after object_get().
Created attachment 20446 [details] [review] new patch
I've attached a new patch which switches to G_TYPE_STRV and adds some examples to the docs. Regarding generic array marshalling, I would envision the following in g_object_set_valist(): if (G_IS_PARAM_SPEC_VALUE_ARRAY (pspec) && G_PARAM_SPEC_VALUE_ARRAY (pspec)->element_spec != null) { gint n = G_PARAM_SPEC_VALUE_ARRAY (pspec)->fixed_n_elements; if (n == 0) { /* collect an integer and assign it to n */ } /* collect n values of type element_spec and put them in * a value array */ } else { /* collect as before */ }