How to define and implement interfaces

Defining interfaces

The theory behind how GObject interfaces work is given in the section called “Non-instantiable classed types: interfaces”; this section covers how to define and implement an interface.

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
/*
 * Copyright/Licensing information.
 */

#ifndef __MAMAN_IBAZ_H__
#define __MAMAN_IBAZ_H__

#include <glib-object.h>

G_BEGIN_DECLS

#define MAMAN_TYPE_IBAZ maman_ibaz_get_type ()
G_DECLARE_INTERFACE (MamanIbaz, maman_ibaz, MAMAN, IBAZ, GObject)

struct _MamanIbazInterface
{
  GTypeInterface parent_iface;

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

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

G_END_DECLS

#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 function is called _GET_IFACE (and is defined by G_DECLARE_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 GTypeInterface, not GObjectClass.

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, G_TYPE_OBJECT);

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_IFACE (self)->do_action (self);
}

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

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