How To define implement an Interface?

Once the interface is defined, implementing it is rather trivial. Source code showing how to do this for the IBaz interface defined in the previous section is located in sample/interface/maman-baz.{h|c}.

The first step is to define a normal GType. Here, we have decided to use a GType which derives from GObject. Its name is MamanBaz:

#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_BAZ_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), MAMAN_TYPE_BAZ, MamanbazClass))
#define MAMAN_IS_BAZ(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_TYPE_BAZ))
#define MAMAN_IS_BAZ_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MAMAN_TYPE_BAZ))
#define MAMAN_BAZ_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_CLASS ((inst), MAMAN_TYPE_BAZ, MamanbazClass))


typedef struct _MamanBaz MamanBaz;
typedef struct _MamanBazClass MamanBazClass;

struct _MamanBaz {
  GObject parent;
  int instance_member;
};

struct _MamanBazClass {
  GObjectClass parent;
};

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 derives from a weird type.

The second step is to implement maman_baz_get_type:

GType 
maman_baz_get_type (void)
{
  static GType type = 0;
  if (type == 0) {
    static const GTypeInfo info = {
      sizeof (MamanBazClass),
      NULL,   /* base_init */
      NULL,   /* base_finalize */
      NULL,   /* class_init */
      NULL,   /* class_finalize */
      NULL,   /* class_data */
      sizeof (MamanBaz),
      0,      /* n_preallocs */
      baz_instance_init    /* instance_init */
    };
    static const GInterfaceInfo ibaz_info = {
      (GInterfaceInitFunc) baz_interface_init,    /* interface_init */
      NULL,               /* interface_finalize */
      NULL                /* interface_data */
    };
    type = g_type_register_static (G_TYPE_OBJECT,
                                   "MamanBazType",
                                   &info, 0);
    g_type_add_interface_static (type,
                                 MAMAN_TYPE_IBAZ,
                                 &ibaz_info);
  }
  return type;
}

This function is very much like all the similar functions we looked at previously. The only interface-specific code present here is the call to g_type_add_interface_static which is used to inform the type system that this just-registered GType also implements the interface MAMAN_TYPE_IBAZ.

baz_interface_init, the interface initialization function, is also pretty simple:

static void baz_do_action (MamanBaz *self)
{
  g_print ("Baz implementation of IBaz interface Action: 0x%x.\n", self->instance_member);
}
static void
baz_interface_init (gpointer   g_iface,
                    gpointer   iface_data)
{
  MamanIbazInteface *iface = (MamanIbazInteface *)g_iface;
  iface->do_action = (void (*) (MamanIbaz *self))baz_do_action;
}
static void
baz_instance_init (GTypeInstance   *instance,
                   gpointer         g_class)
{
  MamanBaz *self = MAMAN_BAZ(instance);
  self->instance_member = 0xdeadbeaf;
}

baz_interface_init merely initializes the interface methods to the implementations defined by MamanBaz: maman_baz_do_action does nothing very useful but it could :)