Hi, It's rather timely that Owen mentioned the topic of deriving from G_TYPE_BOXED in the Cairo discussion. I've been working on the GLib bindings for the D-BUS messaging system (http://www.freedesktop.org/Software/dbus). The core problem I am running into is that D-BUS has a fully recursive type system which is difficult to map cleanly into GType (in its current form). You can read about the D-BUS type system here: http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-signatures Here is a copy of the DBus tutorial which I've patched to include a discussion of how my current patch to the D-BUS GLib bindings works: http://web.verbum.org/files/dbus-tutorial.html#glib-client The core approach that I've been taking now, as you can see from the above, is to map common D-BUS type signatures to some manually-defined GTypes, and punt the complex and weird ones into a special DBusGValue variant type. This ends up *massively* simplifying the code, both the API and the internal marshalling/demarshalling. However, hand-defining various types such as GArray<guint> is mildly painful; it's even worse for the GHashTable cartesian product. Although I imagine for GHashTable not all of those will be in use; e.g. everyone seems to be using string keys only, and not using e.g. the *int64 as values. Anyways though as you can see in the discussion of arrays in the tutorial, what I essentially want is twofold: 1) A GType for GArray and GHashTable 2) "parameterized" subtypes of these We need the parameterized types because the marshalling code needs to know what type an array contains in order to marshal, and the demarshalling code needs to verify that the demarshalled values match what a client was expecting. I talked with Matthias very briefly about this, and he mentioned that he thought this issue hadn't come up before because in most normal APIs, when you pass down e.g. a GHashTable, the library expects that it maps e.g. string -> uint; it's only with remoting that one needs to manipulate values generically. At first I was hand-defining a GType for each variant of GArray<subtype>, and I wrote a GType for GHashTable<gchararray,gchararray>. However, I decided to try to make this more generic by defining a GType for GArray, and then deriving a "parameterized" subtype from it, using a generic function that looks like this: dbus_g_type_get ("GArray<guint>") dbus_g_type_get ("GHashTable<string,gboolean>") There was really nothing D-BUS specific about this though. It knew about GArray and GHashTable specially, and would register types for them which derived from G_TYPE_BOXED. It would then build a GType for the parameterized version, which derived from the GArray or GHashTable type. However I ran into two problems: 1) Type names can't contain < or > 2) We can't "deep" derive from G_TYPE_BOXED Now, I could give up on defining GTypes for these, but it has two major consequences: 1) Makes the dbus_g_proxy_invoke API significantly more weird... you'd need to e.g. pass DBUS_G_ARRAY and G_TYPE_UINT32, but how do you distinguish? DBUS_G_ARRAY from normal GType? Or perhaps we make it a string-based API, so you say: GArray *arr = g_array_new (FALSE, FALSE, sizeof (guint32)); g_array_append_val (arr, 10); g_array_append_val (arr, 42); guint32 ret; dbus_g_proxy_invoke (proxy, "MyMethod", &error, "gboolean", TRUE, "GArray<guint32>", arr, "", &ret, ""); That'd be a method that took a boolean and an array of uint32 as arguments, and returned a uint32. But...ugly...it would invoke a lot of g_type_from_name () lookups for various builtin types. 2) D-BUS has the idea of a "variant", so a client could get as a return value a GValue which happens to contain an array of uint32. Normally with GValue, you'd test like this: if (G_VALUE_HOLDS_STRING (&value)) ... else if (G_VALUE_HOLDS_UINT (&value)) ... etc. But you can't do that if we can't map GArray<uint32> to a its own GType (because how do you know what the array contains then?) We'd have to map all variants to a special DBusGValue type which you have to manipulate using special functions. And now if glib had an API for manipulating "parameterized" types: else if (g_type_is_a (G_VALUE_TYPE (&value), G_TYPE_ARRAY)) { if (g_type_is_a (g_type_container_parameter (G_VALUE_TYPE (&value)), G_TYPE_UINT)) { GArray *arr; guint i; arr = g_value_get_boxed (&value); for (i = 0; i < arr->len; i++) printf ("%d\n", g_array_index (arr, guint, i)); } else { /* Ignore */ } } else if (g_type_is_a (G_VALUE_TYPE (&value), G_TYPE_HASHTABLE)) { GHashTable *table; const GType *parameters; table = g_value_get_boxed (&value); parameters = g_type_map_parameters (G_VALUE_TYPE (&value)); if (parameters[0] == G_TYPE_STRING && parameters[1] == G_TYPE_STRING) { /* We know know it's a hashtable from string -> string */ const char *val; if ((val = g_hash_table_lookup (table, "foo")) != NULL) { printf ("foo: %s\n", val); } } else { /* Ignore other kinds of hash tables */ } } g_value_unset (&value); /* Note this actually knows how to free the array or hashtable or whatever, including g_strdup() keys etc for the hashtable */ Anyways, what I am tempted to do for now is to continue to manually define GTypes for the common types in use not already defined in GLib (e.g. GArray<guchar> and GHashTable<string,string>). Clients will have to access those types using the existing macros such as DBUS_G_TYPE_STR_STR_HASHTABLE and DBUS_G_TYPE_UINT_ARRAY. If GLib ever gets support for boxed subtypes and adding parameterization metadata to types, then I can change those macros to look like this: #define DBUS_G_TYPE_STR_STR_HASHTABLE (g_type_build_parameterized ("GHashTable<gchararray,gchararray>"))
Attachment:
signature.asc
Description: This is a digitally signed message part