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 three 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 29 30 31 32 33 34 35 36 |
/* * Copyright/Licensing information. */ #ifndef __VIEWER_EDITABLE_H__ #define __VIEWER_EDITABLE_H__ #include <glib-object.h> G_BEGIN_DECLS #define VIEWER_TYPE_EDITABLE viewer_editable_get_type () G_DECLARE_INTERFACE (ViewerEditable, viewer_editable, VIEWER, EDITABLE, GObject) struct _ViewerEditableInterface { GTypeInterface parent_iface; void (*save) (ViewerEditable *self, GError **error); void (*undo) (ViewerEditable *self, guint n_steps); void (*redo) (ViewerEditable *self, guint n_steps); }; void viewer_editable_save (ViewerEditable *self, GError **error); void viewer_editable_undo (ViewerEditable *self, guint n_steps); void viewer_editable_redo (ViewerEditable *self, guint n_steps); G_END_DECLS #endif /* __VIEWER_EDITABLE_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 byG_DECLARE_INTERFACE
).The instance type, ViewerEditable, 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 ViewerEditableInterface is GTypeInterface, not GObjectClass.
The implementation of the ViewerEditable type itself is trivial:
G_DEFINE_INTERFACE
creates aviewer_editable_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 pass0
for this argument when an interface has no prerequisite.viewer_editable_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
viewer_editable_save
,viewer_editable_undo
andviewer_editable_redo
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 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
G_DEFINE_INTERFACE (ViewerEditable, viewer_editable, G_TYPE_OBJECT) static void viewer_editable_default_init (ViewerEditableInterface *iface) { /* add properties and signals to the interface here */ } void viewer_editable_save (ViewerEditable *self, GError **error) { ViewerEditableInterface *iface; g_return_if_fail (VIEWER_IS_EDITABLE (self)); g_return_if_fail (error == NULL || *error == NULL); iface = VIEWER_EDITABLE_GET_IFACE (self); g_return_if_fail (iface->save != NULL); iface->save (self, error); } void viewer_editable_undo (ViewerEditable *self, guint n_steps) { ViewerEditableInterface *iface; g_return_if_fail (VIEWER_IS_EDITABLE (self)); iface = VIEWER_EDITABLE_GET_IFACE (self); g_return_if_fail (iface->undo != NULL); iface->undo (self, n_steps); } void viewer_editable_redo (ViewerEditable *self, guint n_steps) { ViewerEditableInterface *iface; g_return_if_fail (VIEWER_IS_EDITABLE (self)); iface = VIEWER_EDITABLE_GET_IFACE (self); g_return_if_fail (iface->redo != NULL); iface->redo (self, n_steps); } |