## How To define and implement Interfaces?

## How To define 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. The sample source code associated to this section can be found in the documentation's source tarball, in the `sample/interface/maman-ibaz.{h|c}` file.

As above, the first step is to get the header right:

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

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

    GType maman_ibaz_get_type (void);

    void maman_ibaz_do_action (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 implementation of the MamanIbaz type itself is trivial:

- `maman_ibaz_get_type` registers the type in the type system.

- `maman_ibaz_base_init` is expected to register the interface's signals if there are any (we will see a bit (later how to use them). Make sure to use a static local boolean variable to make sure not to run the initialization code twice (as described in the section called “Interface Initialization”, `base_init` is run once for each interface implementation instanciation)

- `maman_ibaz_do_action` dereferences the class structure to access its associated class function and calls it.

    static void
    maman_ibaz_base_init (gpointer g_class)
    {
      static gboolean initialized = FALSE;

      if (!initialized) {
        /* create interface signals here. */
        initialized = TRUE;
      }
    }

    GType
    maman_ibaz_get_type (void)
    {
      static GType type = 0;
      if (type == 0) {
        static const GTypeInfo info = {
          sizeof (MamanIbazInterface),
          maman_ibaz_base_init,   /* base_init */
          NULL,   /* base_finalize */
          NULL,   /* class_init */
          NULL,   /* class_finalize */
          NULL,   /* class_data */
          0,
          0,      /* n_preallocs */
          NULL    /* instance_init */
        };
        type = g_type_register_static (G_TYPE_INTERFACE, "MamanIbaz", &info, 0);
      }
      return type;
    }

    void maman_ibaz_do_action (MamanIbaz *self)
    {
      MAMAN_IBAZ_GET_INTERFACE (self)->do_action (self);
    }