## Implementing interfaces

Once the interface is defined, implementing it is rather trivial.

The first step is to define a normal GObject class, like:

    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
    29
    30
    31
    #ifndef __MAMAN_BAZ_H__
    #define __MAMAN_BAZ_H__

    #include <glib-object.h>

    #define MAMAN_TYPE_BAZ             (maman_baz_get_type ())
    #define MAMAN_BAZ(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_TYPE_BAZ, Mamanbaz))
    #define MAMAN_IS_BAZ(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_TYPE_BAZ))
    #define MAMAN_BAZ_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), MAMAN_TYPE_BAZ, MamanbazClass))
    #define MAMAN_IS_BAZ_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), MAMAN_TYPE_BAZ))
    #define MAMAN_BAZ_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), MAMAN_TYPE_BAZ, MamanbazClass))

    typedef struct _MamanBaz        MamanBaz;
    typedef struct _MamanBazClass   MamanBazClass;

    struct _MamanBaz
    {
      GObject parent_instance;

      gint instance_member;
    };

    struct _MamanBazClass
    {
      GObjectClass parent_class;
    };

    GType maman_baz_get_type (void);

    #endif /* __MAMAN_BAZ_H__ */

There is clearly nothing specifically weird or scary about this header: it does not define any weird API or derive from a weird type.

The second step is to implement MamanBaz by defining its GType. Instead of using `G_DEFINE_TYPE` we use `G_DEFINE_TYPE_WITH_CODE` and the `G_IMPLEMENT_INTERFACE` macros.

    1
    2
    3
    4
    5
    static void maman_ibaz_interface_init (MamanIbazInterface *iface);

    G_DEFINE_TYPE_WITH_CODE (MamanBar, maman_bar, G_TYPE_OBJECT,
                             G_IMPLEMENT_INTERFACE (MAMAN_TYPE_IBAZ,
                                                    maman_ibaz_interface_init))

This definition is very much like all the similar functions we looked at previously. The only interface-specific code present here is the call to `G_IMPLEMENT_INTERFACE`.

Classes can implement multiple interfaces by using multiple calls to `G_IMPLEMENT_INTERFACE` inside the call to `G_DEFINE_TYPE_WITH_CODE`

`maman_baz_interface_init`, the interface initialization function: inside it every virtual method of the interface must be assigned to its implementation:

    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
    static void
    maman_baz_do_action (MamanBaz *self)
    {
      g_print ("Baz implementation of Ibaz interface Action: 0x%x.\n",
               self->instance_member);
    }

    static void
    maman_baz_do_something (MamanBaz *self)
    {
      g_print ("Baz implementation of Ibaz interface Something: 0x%x.\n",
               self->instance_member);
    }

    static void
    maman_ibaz_interface_init (MamanIbazInterface *iface)
    {
      iface->do_action = maman_baz_do_action;
      iface->do_something = maman_baz_do_something;
    }

    static void
    maman_baz_init (MamanBaz *self)
    {
      MamanBaz *self = MAMAN_BAZ (instance);
      self->instance_member = 0xdeadbeaf;
    }