Interface implementation in language bindings



The ideal situation is that someone, using a language binding
to GTK+ could just do:

 class Foo (GtkWidget, GtkCellLayout):
   def start_editing (event):
     [....]

(There is a bit of a problem here in that most languages don't
allow sufficient customization of class initialization to 
actually allow such a simple syntax, so mentally add whatever 
extra syntax or hacks are necessary)

The problem with the above is that hooking 

struct _GtkCellEditableIface
{
  GTypeInterface g_iface;

  [...]

  /* virtual table */
  void (* start_editing) (GtkCellEditable *cell_editable,
                          GdkEvent        *event);
};

into a language binding is hard because we need to assign something
to the 'start_editing' vtable pointer. How we fix this once we have
introspection information inside GTK+?

Here's one scheme.

 typedef (*GInterfaceDemarshal) (GInterfaceDesc *interface_desc,
                                 GMethodDesc    *method_desc,
                                 gpointer        instance,
                                 GArgument      *args,
                                 GArgument      *return_value,
                                 gpointer        data);

 g_type_add_interface_generic (GType               interface_type,
                               GType               iface_type,
                               GInterfaceDemarshal demarshal,
                               gpointer            data);

The way this works is that 

 g_type_add_interface_generic (MY_TYPE_FOO, GTK_TYPE_CELL_EDITABLE,
                               demarshal, data);

Stores GTK_TYPE_CELL_EDITABLE, demarshal, and data off in qdata
associated with MY_TYPE_FOO. Then allocates a structure for 
GtkCellEditableIface and fills in start_editing with a pointer
to:

 void
 _g_generic_demarshal_1 (GTypeInstance *instance);
 { 
   GenericDemarshalData *data;
   GArgument *arguments;
   GArgument return;
   
   data = lookup_demarshal_data (instance, 1);
   /* libffi magic to demarshal to arguments */

   demarshal_data_invoke (data, arguments, &return);

   /* libffi magic to marshal the return value */
 }

We have a big pile of these _1, _2, ... so that we can handle
objects with up to say 256 interface methods that could be 
overridden.

You could similarly have a g_type_register_generic() to
handle virtual method overriding in derivation.

A variant of this is to have GGenericDemarshal as an interface you
can add to a type with demarshal_interface, demarshal_object as methods,
and abbreviate g_type_add_interface_generic() to:

 g_type_add_interface_generic (GType interface_type,
                               GType iface_type);

Regards,
							Owen





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