| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| <title>How to define and implement interfaces</title> |
| <meta name="generator" content="DocBook XSL Stylesheets V1.75.2"> |
| <link rel="home" href="index.html" title="GObject Reference Manual"> |
| <link rel="up" href="pt02.html" title="Part IV. Tutorial"> |
| <link rel="prev" href="howto-gobject-chainup.html" title="Chaining up"> |
| <link rel="next" href="howto-interface-implement.html" title="How To define implement an Interface?"> |
| <meta name="generator" content="GTK-Doc V1.14 (XML mode)"> |
| <link rel="stylesheet" href="style.css" type="text/css"> |
| </head> |
| <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> |
| <table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2"><tr valign="middle"> |
| <td><a accesskey="p" href="howto-gobject-chainup.html"><img src="left.png" width="24" height="24" border="0" alt="Prev"></a></td> |
| <td><a accesskey="u" href="pt02.html"><img src="up.png" width="24" height="24" border="0" alt="Up"></a></td> |
| <td><a accesskey="h" href="index.html"><img src="home.png" width="24" height="24" border="0" alt="Home"></a></td> |
| <th width="100%" align="center">GObject Reference Manual</th> |
| <td><a accesskey="n" href="howto-interface-implement.html"><img src="right.png" width="24" height="24" border="0" alt="Next"></a></td> |
| </tr></table> |
| <div class="chapter" title="How to define and implement interfaces"> |
| <div class="titlepage"><div><div><h2 class="title"> |
| <a name="howto-interface"></a>How to define and implement interfaces</h2></div></div></div> |
| <div class="toc"><dl> |
| <dt><span class="sect1"><a href="howto-interface.html#howto-interface-define">How to define interfaces</a></span></dt> |
| <dt><span class="sect1"><a href="howto-interface-implement.html">How To define implement an Interface?</a></span></dt> |
| <dt><span class="sect1"><a href="ch06s03.html">Interface definition prerequisites</a></span></dt> |
| <dt><span class="sect1"><a href="howto-interface-properties.html">Interface Properties</a></span></dt> |
| </dl></div> |
| <div class="sect1" title="How to define interfaces"> |
| <div class="titlepage"><div><div><h2 class="title" style="clear: both"> |
| <a name="howto-interface-define"></a>How to define interfaces</h2></div></div></div> |
| <p> |
| The bulk of interface definition has already been shown in <a class="xref" href="gtype-non-instantiable-classed.html" title="Non-instantiable classed types: interfaces">the section called “Non-instantiable classed types: interfaces”</a> |
| but I feel it is needed to show exactly how to create an interface. |
| </p> |
| <p> |
| As above, the first step is to get the header right: |
| </p> |
| <pre class="programlisting"> |
| #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_iface; |
| |
| void (*do_action) (MamanIbaz *self); |
| }; |
| |
| GType maman_ibaz_get_type (void); |
| |
| void maman_ibaz_do_action (MamanIbaz *self); |
| |
| #endif /* __MAMAN_IBAZ_H__ */ |
| </pre> |
| <p> |
| This code is the same as the code for a normal <span class="type"><a class="link" href="gobject-Type-Information.html#GType" title="GType">GType</a></span> |
| which derives from a <span class="type"><a class="link" href="gobject-The-Base-Object-Type.html#GObject">GObject</a></span> except for a few details: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"><p> |
| The <code class="function">_GET_CLASS</code> macro is called <code class="function">_GET_INTERFACE</code> |
| and not implemented with <code class="function">G_TYPE_INSTANCE_GET_CLASS</code> |
| but with <code class="function">G_TYPE_INSTANCE_GET_INTERFACE</code>. |
| </p></li> |
| <li class="listitem"><p> |
| The instance type, <span class="type">MamanIbaz</span> is not fully defined: it is |
| used merely as an abstract type which represents an instance of |
| whatever object which implements the interface. |
| </p></li> |
| <li class="listitem"><p> |
| The parent of the <span class="type">MamanIbazInterface</span> is not |
| <span class="type">GObjectClass</span> but <span class="type">GTypeInterface</span>. |
| </p></li> |
| </ul></div> |
| <p> |
| </p> |
| <p> |
| The implementation of the <span class="type">MamanIbaz</span> type itself is trivial: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"><p><code class="function">maman_ibaz_get_type</code> registers the |
| type in the type system. |
| </p></li> |
| <li class="listitem"><p><code class="function">maman_ibaz_base_init</code> 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 |
| <a class="xref" href="gtype-non-instantiable-classed.html#gtype-non-instantiable-classed-init" title="Interface Initialization">the section called “Interface Initialization”</a>, |
| <code class="function">base_init</code> is run once for each interface implementation |
| instantiation)</p></li> |
| <li class="listitem"><p><code class="function">maman_ibaz_do_action</code> dereferences |
| the class structure to access its associated class function and calls it. |
| </p></li> |
| </ul></div> |
| <p> |
| </p> |
| <pre class="programlisting"> |
| static void |
| maman_ibaz_base_init (gpointer g_class) |
| { |
| static gboolean is_initialized = FALSE; |
| |
| if (!is_initialized) |
| { |
| /* add properties and signals to the interface here */ |
| |
| is_initialized = TRUE; |
| } |
| } |
| |
| GType |
| maman_ibaz_get_type (void) |
| { |
| static GType iface_type = 0; |
| if (iface_type == 0) |
| { |
| static const GTypeInfo info = { |
| sizeof (MamanIbazInterface), |
| maman_ibaz_base_init, /* base_init */ |
| NULL, /* base_finalize */ |
| }; |
| |
| iface_type = g_type_register_static (G_TYPE_INTERFACE, "MamanIbaz", |
| &info, 0); |
| } |
| |
| return iface_type; |
| } |
| |
| void |
| maman_ibaz_do_action (MamanIbaz *self) |
| { |
| g_return_if_fail (MAMAN_IS_IBAZ (self)); |
| |
| MAMAN_IBAZ_GET_INTERFACE (self)->do_action (self); |
| } |
| </pre> |
| <p> |
| </p> |
| </div> |
| </div> |
| <div class="footer"> |
| <hr> |
| Generated by GTK-Doc V1.14</div> |
| </body> |
| </html> |