Re: Interface implementation in language bindings



On Fri, 2005-02-25 at 17:21 -0500, Owen Taylor wrote:
>The ideal situation is that someone, using a language binding
>to GTK+ could just do:
>
> class Foo (GtkWidget, GtkCellLayout):
>   def start_editing (event):
>     [....]

  s/start_editing/do_start_editing/ and you have the pygtk 2.5 solution
for GInterface implementation.  In pygtk, method 'foo' calls the
implementation method of the interface ("client" part), while do_foo is
defined by the user to provide an implementation ("server" part).

  Same thing for virtual methods, which are also recently supported in
pygtk.


>(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.

  I was kind of following your proposal, in spite of its complexity, but
I was expecting to see, in _g_generic_demarshal_1, a function pointer of
type GInterfaceDemarshal somewhere, and it being actually used.
Otherwise, why bother defining it and registering it in the first place?

>
>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);

  Hm... not sure about this alternative, seems a bit indirect route to
accomplish the same that is more explicit/clear in the first proposal.

  Anyway, this stuff is starting to look good! :-)

  Regards.

-- 
Gustavo J. A. M. Carneiro
<gjc inescporto pt> <gustavo users sourceforge net>
The universe is always one step beyond logic




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