Re: howto write an interface



On Mon, Sep 06, 2010 at 09:05:37PM +0200, joel krähemann wrote:
> Hi, I want to write an interface with glib-object. The situation is a
> parent object implements the interface, but the subclass should
> overwrite the function pointers in the interface. The parent class
> contains the following code in the function ags_recall_get_type:
> 
> ...
> 
> static const GInterfaceInfo ags_connectable_interface_info = {
>   (GInterfaceInitFunc) ags_recall_connectable_interface_init,
>   NULL, /* interface_finalize */
>   NULL, /* interface_data */
> };
> 
> ...
> 
> g_type_add_interface_static(ags_type_recall,
> 			    AGS_TYPE_CONNECTABLE,
>                             &ags_connectable_interface_info);
> 
> ...
> 
> AgsRecall has subclasses which should overwrite the functions, but I
> don't know what's the proper way in the subclass to do so. How do I tell
> GInterface to call a function of the subclass to overwrite?
> One more, is it correct to make an object cast on the interface e.g.
> (where AgsConnectable is an interface which is implemented by
> AgsRecall):
> 
> void
> ags_recall_connect(AgsConnectable connectable)
> {
>   AGS_RECALL(connectable);
> 
>   ...
> }

This sounds somehow backwards.

1) You define an interface, with a virtual table, i.e. struct
AgsConnectableInterface, containing the method connect():

    struct _AgsConnectableInterface {
        GTypeInterface parent;

        void (*connect)(AgsConnectable *connectable);
    };


2) Then standard macros AGS_TYPE_CONNECTABLE, AGS_CONNECTABLE,
AGS_IS_CONNECTABLE, AGS_CONNECTABLE_GET_INTERFACE, see the docs.

3) Methods of this interface, e.g. ags_connectable_connect(), get
AgsConnectable* as the argument and look up the virtual method to call:

    void
    ags_connectable_connect(AgsConnectable *connectable)
    {
        void (*connect_method)(AgsConnectable*);

        g_return_if_fail(AGS_IS_CONNECTABLE(connectable));
        connect_method = AGS_CONNECTABLE_GET_INTERFACE(connectable)->connect;
        g_return_if_fail(connect_method);
        connect_method(connectable);
    }

There is no public ags_recall_connect() as this makes no sense.  To
invoke the connect() method of AgsRecall (or any other class
implementing the interface) you call

    ags_connectable_connect(AGS_CONNECTABLE(recall));

4) Each class implementing the interface, including subclasses of
something that already implements the interface, does

    {
        static const GInterfaceInfo ags_connectable_interface_info = {
            (GInterfaceInitFunc)ags_recall_connectable_init, NULL, NULL
        };
        g_type_add_interface_static(g_define_type_id,
                                    AGS_TYPE_CONNECTABLE,
                                    &ags_connectable_interface_info);
    }

in the type init function ags_recall_type_init().

5) Function ags_recall_connectable_init() gets the virtual table
AgsConnectableInterface as the argument and fills it:

    static void
    ags_recall_connectable_init(AgsConnectableInterface *iface)
    {
        iface->connect = ags_recall_connect;
    }

where ags_recall_connect() is a static function implementing the method,
not public.

Yeti



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