## How to define and implement interfaces

## Defining interfaces

The bulk of interface definition has already been shown in the section called “Non-instantiable classed types: interfaces” but I feel it is needed to show exactly how to create an interface.

As above, the first step is to get the header right. This interface defines two methods:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #ifndef __MAMAN_IBAZ_H__
    #define __MAMAN_IBAZ_H__

    #include <glib-object.h>

    #define MAMAN_TYPE_IBAZ                 (maman_ibaz_get_type ())
    #define MAMAN_IBAZ(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_TYPE_IBAZ, MamanIbaz))
    #define MAMAN_IS_IBAZ(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_TYPE_IBAZ))
    #define MAMAN_IBAZ_GET_INTERFACE(inst)  (G_TYPE_INSTANCE_GET_INTERFACE ((inst), MAMAN_TYPE_IBAZ, MamanIbazInterface))

    typedef struct _MamanIbaz               MamanIbaz; /* dummy object */
    typedef struct _MamanIbazInterface      MamanIbazInterface;

    struct _MamanIbazInterface
    {
      GTypeInterface parent_iface;

      void (*do_action) (MamanIbaz *self);
      void (*do_something) (MamanIbaz *self);
    };

    GType maman_ibaz_get_type (void);

    void maman_ibaz_do_action    (MamanIbaz *self);
    void maman_ibaz_do_something (MamanIbaz *self);

    #endif /* __MAMAN_IBAZ_H__ */

This code is the same as the code for a normal GType which derives from a GObject except for a few details:

- The `_GET_CLASS` macro is called `_GET_INTERFACE` and not implemented with `G_TYPE_INSTANCE_GET_CLASS` but with `G_TYPE_INSTANCE_GET_INTERFACE`.

- The instance type, MamanIbaz is not fully defined: it is used merely as an abstract type which represents an instance of whatever object which implements the interface.

- The parent of the MamanIbazInterface is not GObjectClass but GTypeInterface.

The implementation of the MamanIbaz type itself is trivial:

- `G_DEFINE_INTERFACE` creates a `maman_ibaz_get_type` function which registers the type in the type system. The third argument is used to define a prerequisite interface (which we'll talk about more later). Just pass `0` for this argument when an interface has no prerequisite.

- `maman_ibaz_default_init` is expected to register the interface's signals if there are any (we will see a bit later how to use them).

- The interface methods `maman_ibaz_do_action` and `maman_ibaz_do_something` dereference the interface structure to access its associated interface function and call it.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    G_DEFINE_INTERFACE (MamanIbaz, maman_ibaz, 0);

    static void
    maman_ibaz_default_init (MamanIbazInterface *iface)
    {
        /* add properties and signals to the interface here */
    }

    void
    maman_ibaz_do_action (MamanIbaz *self)
    {
      g_return_if_fail (MAMAN_IS_IBAZ (self));

      MAMAN_IBAZ_GET_INTERFACE (self)->do_action (self);
    }

    void
    maman_ibaz_do_something (MamanIbaz *self)
    {
      g_return_if_fail (MAMAN_IS_IBAZ (self));

      MAMAN_IBAZ_GET_INTERFACE (self)->do_something (self);
    }