Re: dbus glib bindings: deriving from G_TYPE_BOXED, parameterized types



Le vendredi 13 mai 2005 �3:01 -0400, Colin Walters a �it : 
> 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 think GTypes can handle this.
Here is the api:

GType g_hash_table_get_type (void);
GType g_hash_table_get_type (GType keys, GType values);
The latter returning a subtype of the former, and the former being not
instanciable.

Basically g_hash_table_get_type can use g_type_module_register_type
whenever it encounters a name that hasn't been registered. The GTypeInfo
functions don't need more parameters, the type data can be passed
through type_info->class_data to class_init, stored in a class field and
then retrieved from the class (or from an instance using the
G_HASHTABLE_GET_CLASS macro).

g_hashtable_parameterized_class_init (GHashtableParameterizedClass* c,
GHashtableTypeParameters* t)
	c->key_type = t->key_type;
	c->val_type = t->val_type;
	...
}

g_hashtable_get_key_type (GHashTable�Instance* h) {
	return G_HASHTABLE_GET_CLASS (h)->key_type;
}



GType g_hashtable_get_parameterized_type (GType keys, GType values) {
	//GNU C's variable length arrays would be a good (faster) idea
	char* name = asprintf ("GtkHashTable<%s,%s>",
		g_type_name (keys)
		g_type_name (values));
		GType * ret = g_type_from_name (name);
	if (!ret) {
		module->class_data = type_parameters_new (keys, values);
		g_type_module_register_type (
			module,
			g_hashtable_get_type (),
			name,
			type_info,
			type_flags);
		g_free (module->class_data);
	}
	free(name);
	return ret;
}

The string manipulation is a pity, but otherwise it works.


I'd like to plug how much I like the languages that do parametric
polymorphism or have a module system: in OCaml the type system can
handle polymorphism, statically, safely, and without even having to
declare a variable's type. snip:

module H = Hashtbl
let h = H.create 10
H.add h a_gtk_window [1;2;3]
H.remove h a_gtk_window
(*this won't compile:*)
H.add h another_gtk_window ["A"; "B"]
	This expression has type string but is here used with type int





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]