mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-11-04 10:08:56 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1825 lines
		
	
	
		
			67 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
			
		
		
	
	
			1825 lines
		
	
	
		
			67 KiB
		
	
	
	
		
			XML
		
	
	
	
	
	
<?xml version='1.0' encoding="ISO-8859-1"?>
 | 
						|
<!DOCTYPE part PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" 
 | 
						|
               "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
 | 
						|
]>
 | 
						|
<part label="IV">
 | 
						|
  <title>Tutorial</title>
 | 
						|
  <partintro>
 | 
						|
    <para>
 | 
						|
      This chapter tries to answer the real-life questions of users and presents
 | 
						|
      the most common scenario use cases I could come up with.
 | 
						|
      The use cases are presented from most likely to less likely.
 | 
						|
    </para>
 | 
						|
  </partintro>
 | 
						|
 | 
						|
<chapter id="howto-gobject">
 | 
						|
  <title>How to define and implement a new GObject</title>
 | 
						|
  
 | 
						|
  <para>
 | 
						|
    Clearly, this is one of the most common questions people ask: they just
 | 
						|
    want to crank code and implement a subclass of a GObject. Sometimes because
 | 
						|
    they want to create their own class hierarchy, sometimes because they want
 | 
						|
    to subclass one of GTK+'s widget. This chapter will focus on the 
 | 
						|
    implementation of a subtype of GObject.
 | 
						|
  </para>
 | 
						|
 | 
						|
  <sect1 id="howto-gobject-header">
 | 
						|
    <title>Boilerplate header code</title>
 | 
						|
    
 | 
						|
    <para>
 | 
						|
      The first step before writing the code for your GObject is to write the
 | 
						|
      type's header which contains the needed type, function and macro
 | 
						|
      definitions. Each of these elements is nothing but a convention which
 | 
						|
      is followed not only by GTK+'s code but also by most users of GObject.
 | 
						|
      If you feel the need not to obey the rules stated below, think about it
 | 
						|
      twice:
 | 
						|
      <itemizedlist>
 | 
						|
        <listitem><para>If your users are a bit accustomed to GTK+ code or any
 | 
						|
        GLib code, they will be a bit surprised and getting used to the
 | 
						|
        conventions you decided upon will take time (money) and will make them
 | 
						|
        grumpy (not a good thing)</para></listitem>
 | 
						|
        <listitem><para>You must assess the fact that these conventions might
 | 
						|
        have been designed by both smart and experienced people: maybe they
 | 
						|
        were at least partly right. Try to put your ego aside.</para></listitem>
 | 
						|
      </itemizedlist>
 | 
						|
      It is, nevertheless, important to note that these rules generally apply
 | 
						|
      to code that is meant to be called by third parties; it is perfectly
 | 
						|
      possible to write a valid, self-contained GObject types without most of
 | 
						|
      the boilerplate used in this tutorial; most of the boilerplate is also
 | 
						|
      not strictly required if you plan to use the GObject types only through
 | 
						|
      language bindings based on introspection.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      Pick a name convention for your headers and source code and stick to it:
 | 
						|
      <itemizedlist>
 | 
						|
        <listitem><para>use a dash to separate the prefix from the typename:
 | 
						|
        <filename>maman-bar.h</filename> and <filename>maman-bar.c</filename>
 | 
						|
        (this is the convention used by Nautilus and most GNOME libraries).</para></listitem>
 | 
						|
        <listitem><para>use an underscore to separate the prefix from the
 | 
						|
        typename: <filename>maman_bar.h</filename> and
 | 
						|
        <filename>maman_bar.c</filename>.</para></listitem>
 | 
						|
        <listitem><para>Do not separate the prefix from the typename:
 | 
						|
        <filename>mamanbar.h</filename> and <filename>mamanbar.c</filename>.
 | 
						|
        (this is the convention used by GTK+)</para></listitem>
 | 
						|
      </itemizedlist>
 | 
						|
      Some people like the first two solutions better: it makes reading file
 | 
						|
      names easier for those with poor eyesight.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      When you need some private (internal) declarations in several
 | 
						|
      (sub)classes, you can define them in a private header file which
 | 
						|
      is often named by appending the <emphasis>private</emphasis> keyword
 | 
						|
      to the public header name. For example, one could use
 | 
						|
      <filename>maman-bar-private.h</filename>,
 | 
						|
      <filename>maman_bar_private.h</filename> or
 | 
						|
      <filename>mamanbarprivate.h</filename>. Typically, such private header
 | 
						|
      files are not installed.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      The basic conventions for any header which exposes a GType are described
 | 
						|
      in <xref linkend="gtype-conventions"/>. Most GObject-based code also
 | 
						|
      obeys one of of the following conventions: pick one and stick to it.
 | 
						|
      <itemizedlist>
 | 
						|
        <listitem><para>
 | 
						|
            If you want to declare a type named bar with prefix maman, name the type instance
 | 
						|
            <function>MamanBar</function> and its class <function>MamanBarClass</function>
 | 
						|
            (name is case-sensitive). It is customary to declare them with code similar to the 
 | 
						|
            following:
 | 
						|
<programlisting>
 | 
						|
/*
 | 
						|
 * Copyright/Licensing information.
 | 
						|
 */
 | 
						|
 | 
						|
/* inclusion guard */
 | 
						|
#ifndef __MAMAN_BAR_H__
 | 
						|
#define __MAMAN_BAR_H__
 | 
						|
 | 
						|
#include <glib-object.h>
 | 
						|
/*
 | 
						|
 * Potentially, include other headers on which this header depends.
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
 * Type macros.
 | 
						|
 */
 | 
						|
#define MAMAN_TYPE_BAR                  (maman_bar_get_type ())
 | 
						|
#define MAMAN_BAR(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_TYPE_BAR, MamanBar))
 | 
						|
#define MAMAN_IS_BAR(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_TYPE_BAR))
 | 
						|
#define MAMAN_BAR_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), MAMAN_TYPE_BAR, MamanBarClass))
 | 
						|
#define MAMAN_IS_BAR_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), MAMAN_TYPE_BAR))
 | 
						|
#define MAMAN_BAR_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), MAMAN_TYPE_BAR, MamanBarClass))
 | 
						|
 | 
						|
typedef struct _MamanBar        MamanBar;
 | 
						|
typedef struct _MamanBarClass   MamanBarClass;
 | 
						|
 | 
						|
struct _MamanBar
 | 
						|
{
 | 
						|
  /* Parent instance structure */
 | 
						|
  GObject parent_instance;
 | 
						|
 | 
						|
  /* instance members */
 | 
						|
};
 | 
						|
 | 
						|
struct _MamanBarClass
 | 
						|
{
 | 
						|
  /* Parent class structure */
 | 
						|
  GObjectClass parent_class;
 | 
						|
 | 
						|
  /* class members */
 | 
						|
};
 | 
						|
 | 
						|
/* used by MAMAN_TYPE_BAR */
 | 
						|
GType maman_bar_get_type (void);
 | 
						|
 | 
						|
/*
 | 
						|
 * Method definitions.
 | 
						|
 */
 | 
						|
 | 
						|
#endif /* __MAMAN_BAR_H__ */
 | 
						|
</programlisting>
 | 
						|
          </para></listitem>
 | 
						|
        <listitem><para>
 | 
						|
            Types that require per-instance private data should use the
 | 
						|
            G_DEFINE_TYPE_WITH_PRIVATE() macro, or use the G_ADD_PRIVATE()
 | 
						|
            macro with the G_DEFINE_TYPE_WITH_CODE() or the G_DEFINE_TYPE_EXTENDED()
 | 
						|
            macros. The private structure is then defined in the .c file,
 | 
						|
            and can be accessed using the <function>get_instance_private()</function>
 | 
						|
            function generated by the G_DEFINE_TYPE_* macros.
 | 
						|
<programlisting>
 | 
						|
struct _MamanBarPrivate
 | 
						|
{
 | 
						|
  int hsize;
 | 
						|
};
 | 
						|
 | 
						|
G_DEFINE_TYPE_WITH_PRIVATE (MamanBar, maman_bar, G_TYPE_OBJECT)
 | 
						|
 | 
						|
static void
 | 
						|
maman_bar_class_init (MamanBarClass *klass)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_bar_init (MamanBar *self)
 | 
						|
{
 | 
						|
  /* maman_bar_get_instance_private() is generated by G_DEFINE_TYPE_WITH_PRIVATE()
 | 
						|
   * above, and it's local to the current compilation unit.
 | 
						|
   */
 | 
						|
  MamanBarPrivate *priv = maman_bar_get_instance_private (self);
 | 
						|
 | 
						|
  priv->hsize = 42;
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
          </para></listitem>
 | 
						|
 | 
						|
          <listitem><para>
 | 
						|
            Most GNOME libraries use a pointer inside the instance structure
 | 
						|
            for simpler access to the private data structure, as described by
 | 
						|
            Herb Sutter in his Pimpl article (see <ulink url="http://www.gotw.ca/gotw/024.htm">Compilation Firewalls</ulink>
 | 
						|
            and <ulink url="http://www.gotw.ca/gotw/028.htm">The Fast Pimpl Idiom</ulink>
 | 
						|
            for reference). If you opt to use this idiom, you can assign the
 | 
						|
            pointer inside the instance initialization function, e.g.:
 | 
						|
<programlisting>
 | 
						|
G_DEFINE_TYPE_WITH_PRIVATE (MamanBar, maman_bar, G_TYPE_OBJECT)
 | 
						|
 | 
						|
struct _MamanBarPrivate
 | 
						|
{
 | 
						|
  int hsize;
 | 
						|
};
 | 
						|
 | 
						|
static void
 | 
						|
maman_bar_class_init (MamanBarClass *klass)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_bar_init (MamanBar *self)
 | 
						|
{
 | 
						|
  self->priv = maman_bar_get_instance_private (self);
 | 
						|
  self->priv->hsize = 42;
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
          </para></listitem>
 | 
						|
      </itemizedlist>
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      Finally, there are different header include conventions. Again, pick one
 | 
						|
      and stick to it. I personally use indifferently any of the two, depending
 | 
						|
      on the codebase I work on: the rule, as always, is consistency.
 | 
						|
      <itemizedlist>
 | 
						|
        <listitem><para>
 | 
						|
            Some people add at the top of their headers a number of #include
 | 
						|
            directives to pull in all the headers needed to compile client
 | 
						|
            code. This allows client code to simply #include "maman-bar.h".
 | 
						|
          </para></listitem>
 | 
						|
        <listitem><para>
 | 
						|
            Other do not #include anything and expect the client to #include
 | 
						|
            themselves the headers they need before including your header. This
 | 
						|
            speeds up compilation because it minimizes the amount of
 | 
						|
            pre-processor work. This can be used in conjunction with the
 | 
						|
            re-declaration of certain unused types in the client code to
 | 
						|
            minimize compile-time dependencies and thus speed up compilation.
 | 
						|
          </para></listitem>
 | 
						|
      </itemizedlist>
 | 
						|
    </para>
 | 
						|
      
 | 
						|
  </sect1>
 | 
						|
 | 
						|
  <sect1 id="howto-gobject-code">
 | 
						|
    <title>Boilerplate code</title>
 | 
						|
 | 
						|
    <para>
 | 
						|
      In your code, the first step is to #include the needed headers: depending
 | 
						|
      on your header include strategy, this can be as simple as
 | 
						|
      <literal>#include "maman-bar.h"</literal> or as complicated as tens
 | 
						|
      of #include lines ending with <literal>#include "maman-bar.h"</literal>:
 | 
						|
<programlisting>
 | 
						|
/*
 | 
						|
 * Copyright information
 | 
						|
 */
 | 
						|
 | 
						|
#include "maman-bar.h"
 | 
						|
 | 
						|
/* If you use Pimpls, include the private structure 
 | 
						|
 * definition here. Some people create a maman-bar-private.h header
 | 
						|
 * which is included by the maman-bar.c file and which contains the
 | 
						|
 * definition for this private structure.
 | 
						|
 */
 | 
						|
struct _MamanBarPrivate {
 | 
						|
  int member_1;
 | 
						|
  /* stuff */
 | 
						|
};
 | 
						|
 | 
						|
/* 
 | 
						|
 * forward definitions
 | 
						|
 */
 | 
						|
</programlisting>
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      Call the <function>G_DEFINE_TYPE</function> macro using the name
 | 
						|
      of the type, the prefix of the functions and the parent GType to
 | 
						|
      reduce the amount of boilerplate needed. This macro will:
 | 
						|
 | 
						|
      <itemizedlist>
 | 
						|
        <listitem><simpara>implement the <function>maman_bar_get_type</function>
 | 
						|
        function</simpara></listitem>
 | 
						|
        <listitem><simpara>define a parent class pointer accessible from
 | 
						|
        the whole .c file</simpara></listitem>
 | 
						|
      </itemizedlist>
 | 
						|
 | 
						|
<programlisting>
 | 
						|
G_DEFINE_TYPE (MamanBar, maman_bar, G_TYPE_OBJECT)
 | 
						|
</programlisting>
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      It is also possible to use the
 | 
						|
      <function>G_DEFINE_TYPE_WITH_CODE</function> macro to control the
 | 
						|
      get_type function implementation - for instance, to add a call to
 | 
						|
      <function>G_IMPLEMENT_INTERFACE</function> macro which will
 | 
						|
      call the <function>g_type_implement_interface</function> function,
 | 
						|
      or call the <function>G_ADD_PRIVATE</function> macro will add an
 | 
						|
      instance private data structure.
 | 
						|
    </para>
 | 
						|
  </sect1>
 | 
						|
 | 
						|
  <sect1 id="howto-gobject-construction">
 | 
						|
    <title>Object Construction</title>
 | 
						|
 | 
						|
    <para>
 | 
						|
      People often get confused when trying to construct their GObjects because of the
 | 
						|
      sheer number of different ways to hook into the objects's construction process: it is
 | 
						|
      difficult to figure which is the <emphasis>correct</emphasis>, recommended way.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      <xref linkend="gobject-construction-table"/> shows what user-provided functions
 | 
						|
      are invoked during object instantiation and in which order they are invoked.
 | 
						|
      A user looking for the equivalent of the simple C++ constructor function should use
 | 
						|
      the instance_init method. It will be invoked after all the parent's instance_init
 | 
						|
      functions have been invoked. It cannot take arbitrary construction parameters 
 | 
						|
      (as in C++) but if your object needs arbitrary parameters to complete initialization,
 | 
						|
      you can use construction properties.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      Construction properties will be set only after all instance_init functions have run.
 | 
						|
      No object reference will be returned to the client of <function><link linkend="g-object-new">g_object_new</link></function>
 | 
						|
      until all the construction properties have been set.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      It is important to note that object construction cannot <emphasis>ever</emphasis>
 | 
						|
      fail. If you require a fallible GObject construction, you can use the
 | 
						|
      GInitable and GAsyncInitable interfaces provided by the GIO library
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      As such, I would recommend writing the following code first:
 | 
						|
<programlisting>
 | 
						|
G_DEFINE_TYPE_WITH_PRIVATE (MamanBar, maman_bar, G_TYPE_OBJECT)
 | 
						|
 | 
						|
static void
 | 
						|
maman_bar_class_init (MamanBarClass *klass)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_bar_init (MamanBar *self)
 | 
						|
{
 | 
						|
  self->priv = maman_bar_get_instance_private (self);
 | 
						|
 | 
						|
  /* initialize all public and private members to reasonable default values. */
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      If you need special construction properties, install the properties in
 | 
						|
      the <function>class_init()</function> function, override the <function>set_property()</function>
 | 
						|
      and <function>get_property()</function> methods of the GObject class,
 | 
						|
      and implement them as described by <xref linkend="gobject-properties"/>.
 | 
						|
<informalexample><programlisting>
 | 
						|
enum {
 | 
						|
  PROP_0,
 | 
						|
 | 
						|
  PROP_MAMAN,
 | 
						|
 | 
						|
  N_PROPERTIES
 | 
						|
};
 | 
						|
 | 
						|
/* Keep a pointer to the properties definition */
 | 
						|
static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
 | 
						|
 | 
						|
static void
 | 
						|
bar_class_init (MamanBarClass *klass)
 | 
						|
{
 | 
						|
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 | 
						|
 | 
						|
  gobject_class->set_property = bar_set_property;
 | 
						|
  gobject_class->get_property = bar_get_property;
 | 
						|
 | 
						|
  obj_properties[PROP_MAMAN] =
 | 
						|
    g_param_spec_string ("maman",
 | 
						|
                         "Maman construct prop",
 | 
						|
                         "Set maman's name",
 | 
						|
                         "no-name-set" /* default value */,
 | 
						|
                         G_PARAM_CONSTRUCT_ONLY |
 | 
						|
                         G_PARAM_READWRITE |
 | 
						|
                         G_PARAM_STATIC_STRINGS);
 | 
						|
 | 
						|
  g_object_class_install_properties (gobject_class,
 | 
						|
                                     N_PROPERTIES,
 | 
						|
                                     obj_properties);
 | 
						|
}
 | 
						|
</programlisting></informalexample>
 | 
						|
      If you need this, make sure you can build and run code similar to the
 | 
						|
      code shown above. Also, make sure your construct properties can be set
 | 
						|
      without side effects during construction.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      Some people sometimes need to complete the initialization of a instance
 | 
						|
      of a type only after the properties passed to the constructors have been
 | 
						|
      set. This is possible through the use of the <function>constructor()</function>
 | 
						|
      class method as described in <xref linkend="gobject-instantiation"/> or,
 | 
						|
      more simply, using the <function>constructed()</function> class method
 | 
						|
      available since GLib 2.12. Note that the <function>constructed()</function>
 | 
						|
      virtual function will only be invoked after the properties marked as
 | 
						|
      G_PARAM_CONSTRUCT_ONLY or G_PARAM_CONSTRUCT have been consumed, but
 | 
						|
      before the regular properties passed to <function>g_object_new()</function>
 | 
						|
      have been set.
 | 
						|
    </para>
 | 
						|
  </sect1>
 | 
						|
 | 
						|
  <sect1 id="howto-gobject-destruction">
 | 
						|
    <title>Object Destruction</title>
 | 
						|
 | 
						|
    <para>
 | 
						|
      Again, it is often difficult to figure out which mechanism to use to
 | 
						|
      hook into the object's destruction process: when the last
 | 
						|
      <function><link linkend="g-object-unref">g_object_unref</link></function>
 | 
						|
      function call is made, a lot of things happen as described in
 | 
						|
      <xref linkend="gobject-destruction-table"/>.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      The destruction process of your object might be split in two different
 | 
						|
      phases: dispose and the finalize. This split is necessary to handle
 | 
						|
      potential cycles due to the nature of the reference counting mechanism
 | 
						|
      used by GObject, as well as dealing with temporary vivification of
 | 
						|
      instances in case of signal emission during the destruction sequence.
 | 
						|
<programlisting>
 | 
						|
struct _MamanBarPrivate
 | 
						|
{
 | 
						|
  GObject *an_object;
 | 
						|
 | 
						|
  gchar *a_string;
 | 
						|
};
 | 
						|
 | 
						|
G_DEFINE_TYPE_WITH_PRIVATE (MamanBar, maman_bar, G_TYPE_OBJECT)
 | 
						|
 | 
						|
static void
 | 
						|
maman_bar_dispose (GObject *gobject)
 | 
						|
{
 | 
						|
  MamanBar *self = MAMAN_BAR (gobject);
 | 
						|
 | 
						|
  /* In dispose(), you are supposed to free all types referenced from this
 | 
						|
   * object which might themselves hold a reference to self. Generally,
 | 
						|
   * the most simple solution is to unref all members on which you own a 
 | 
						|
   * reference.
 | 
						|
   */
 | 
						|
 | 
						|
  /* dispose() might be called multiple times, so we must guard against
 | 
						|
   * calling g_object_unref() on an invalid GObject by setting the member
 | 
						|
   * NULL; g_clear_object() does this for us, atomically.
 | 
						|
   */
 | 
						|
  g_clear_object (&self->priv->an_object);
 | 
						|
 | 
						|
  /* Always chain up to the parent class; there is no need to check if
 | 
						|
   * the parent class implements the dispose() virtual function: it is
 | 
						|
   * always guaranteed to do so
 | 
						|
   */
 | 
						|
  G_OBJECT_CLASS (maman_bar_parent_class)->dispose (gobject);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_bar_finalize (GObject *gobject)
 | 
						|
{
 | 
						|
  MamanBar *self = MAMAN_BAR (gobject);
 | 
						|
 | 
						|
  g_free (self->priv->a_string);
 | 
						|
 | 
						|
  /* Always chain up to the parent class; as with dispose(), finalize()
 | 
						|
   * is guaranteed to exist on the parent's class virtual function table
 | 
						|
   */
 | 
						|
  G_OBJECT_CLASS (maman_bar_parent_class)->finalize (gobject);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_bar_class_init (MamanBarClass *klass)
 | 
						|
{
 | 
						|
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 | 
						|
 | 
						|
  gobject_class->dispose = maman_bar_dispose;
 | 
						|
  gobject_class->finalize = maman_bar_finalize;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_bar_init (MamanBar *self);
 | 
						|
{
 | 
						|
  self->priv = maman_bar_get_instance_private (self); 
 | 
						|
 | 
						|
  self->priv->an_object = g_object_new (MAMAN_TYPE_BAZ, NULL);
 | 
						|
  self->priv->a_string = g_strdup ("Maman");
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      It is possible that object methods might be invoked after dispose is
 | 
						|
      run and before finalize runs. GObject does not consider this to be a
 | 
						|
      program error: you must gracefully detect this and neither crash nor
 | 
						|
      warn the user, by having a disposed instance revert to an inhert state.
 | 
						|
    </para>
 | 
						|
  </sect1>
 | 
						|
 | 
						|
  <sect1 id="howto-gobject-methods">
 | 
						|
    <title>Object methods</title>
 | 
						|
 | 
						|
    <para>
 | 
						|
      Just as with C++, there are many different ways to define object
 | 
						|
      methods and extend them: the following list and sections draw on
 | 
						|
      C++ vocabulary. (Readers are expected to know basic C++ concepts.
 | 
						|
      Those who have not had to write C++ code recently can refer to e.g.
 | 
						|
      <ulink url="http://www.cplusplus.com/doc/tutorial/"/> to refresh
 | 
						|
      their memories.)
 | 
						|
      <itemizedlist>
 | 
						|
        <listitem><para>
 | 
						|
            non-virtual public methods,
 | 
						|
          </para></listitem>
 | 
						|
        <listitem><para>
 | 
						|
            virtual public methods and
 | 
						|
          </para></listitem>
 | 
						|
        <listitem><para>
 | 
						|
            virtual private methods
 | 
						|
          </para></listitem>
 | 
						|
      </itemizedlist>
 | 
						|
    </para>
 | 
						|
 | 
						|
    <sect2>
 | 
						|
      <title>Non-virtual public methods</title>
 | 
						|
 | 
						|
      <para>
 | 
						|
        These are the simplest: you want to provide a simple method which
 | 
						|
        can act on your object. All you need to do is to provide a function
 | 
						|
        prototype in the header and an implementation of that prototype
 | 
						|
        in the source file.
 | 
						|
<programlisting>
 | 
						|
/* declaration in the header. */
 | 
						|
void maman_bar_do_action (MamanBar *self, /* parameters */);
 | 
						|
 | 
						|
/* implementation in the source file */
 | 
						|
void
 | 
						|
maman_bar_do_action (MamanBar *self, /* parameters */)
 | 
						|
{
 | 
						|
  g_return_if_fail (MAMAN_IS_BAR (self));
 | 
						|
 | 
						|
  /* do stuff here. */
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
      </para>
 | 
						|
    </sect2>
 | 
						|
 | 
						|
    <sect2>
 | 
						|
      <title>Virtual public methods</title>
 | 
						|
 | 
						|
      <para>
 | 
						|
        This is the preferred way to create polymorphic GObjects. All you
 | 
						|
        need to do is to define the common method and its class function in
 | 
						|
        the public header, implement the common method in the source file
 | 
						|
        and re-implement the class function in each object which inherits
 | 
						|
        from you.
 | 
						|
<programlisting>
 | 
						|
/* declaration in maman-bar.h. */
 | 
						|
struct _MamanBarClass
 | 
						|
{
 | 
						|
  GObjectClass parent_class;
 | 
						|
 | 
						|
  /* stuff */
 | 
						|
  void (*do_action) (MamanBar *self, /* parameters */);
 | 
						|
};
 | 
						|
 | 
						|
void maman_bar_do_action (MamanBar *self, /* parameters */);
 | 
						|
 | 
						|
/* implementation in maman-bar.c */
 | 
						|
void
 | 
						|
maman_bar_do_action (MamanBar *self, /* parameters */)
 | 
						|
{
 | 
						|
  g_return_if_fail (MAMAN_IS_BAR (self));
 | 
						|
 | 
						|
  MAMAN_BAR_GET_CLASS (self)->do_action (self, /* parameters */);
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
        The code above simply redirects the do_action call to the relevant
 | 
						|
        class function.
 | 
						|
      </para>
 | 
						|
 | 
						|
      <para>
 | 
						|
        Please, note that it is possible for you to provide a default
 | 
						|
        implementation for this class method in the object's
 | 
						|
        <function>class_init</function> function: initialize the
 | 
						|
        klass->do_action field to a pointer to the actual implementation.
 | 
						|
        By default, class method that are not inherited are initialized to
 | 
						|
        NULL, and thus are to be considered "pure virtual".
 | 
						|
<programlisting>
 | 
						|
static void
 | 
						|
maman_bar_real_do_action_two (MamanBar *self, /* parameters */)
 | 
						|
{
 | 
						|
  /* Default implementation for the virtual method. */
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_bar_class_init (BarClass *klass)
 | 
						|
{
 | 
						|
  /* this is not necessary, except for demonstration purposes.
 | 
						|
   *
 | 
						|
   * pure virtual method: mandates implementation in children.
 | 
						|
   */
 | 
						|
  klass->do_action_one = NULL;
 | 
						|
 | 
						|
  /* merely virtual method. */
 | 
						|
  klass->do_action_two = maman_bar_real_do_action_two;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
maman_bar_do_action_one (MamanBar *self, /* parameters */)
 | 
						|
{
 | 
						|
  g_return_if_fail (MAMAN_IS_BAR (self));
 | 
						|
 | 
						|
  /* if the method is purely virtual, then it is a good idea to
 | 
						|
   * check that it has been overridden before calling it, and,
 | 
						|
   * depending on the intent of the class, either ignore it silently
 | 
						|
   * or warn the user.
 | 
						|
   /
 | 
						|
  if (MAMAN_BAR_GET_CLASS (self)->do_action_one != NULL)
 | 
						|
    MAMAN_BAR_GET_CLASS (self)->do_action_one (self, /* parameters */);
 | 
						|
  else
 | 
						|
    g_warning ("Class '%s' does not override the mandatory "
 | 
						|
               "MamanBarClass.do_action_one() virtual function.",
 | 
						|
               G_OBJECT_TYPE_NAME (self));
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
maman_bar_do_action_two (MamanBar *self, /* parameters */)
 | 
						|
{
 | 
						|
  g_return_if_fail (MAMAN_IS_BAR (self));
 | 
						|
 | 
						|
  MAMAN_BAR_GET_CLASS (self)->do_action_two (self, /* parameters */);
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
      </para>
 | 
						|
    </sect2>
 | 
						|
 | 
						|
    <sect2>
 | 
						|
      <title>Virtual private Methods</title>
 | 
						|
 | 
						|
      <para>
 | 
						|
        These are very similar to Virtual Public methods. They just don't
 | 
						|
        have a public function to call the function directly. The header
 | 
						|
        file contains only a declaration of the class function:
 | 
						|
<programlisting>
 | 
						|
/* declaration in maman-bar.h. */
 | 
						|
struct _MamanBarClass
 | 
						|
{
 | 
						|
  GObjectClass parent;
 | 
						|
 | 
						|
  /* stuff */
 | 
						|
  void (* helper_do_specific_action) (MamanBar *self, /* parameters */);
 | 
						|
};
 | 
						|
 | 
						|
void maman_bar_do_any_action (MamanBar *self, /* parameters */);
 | 
						|
</programlisting>
 | 
						|
        These class functions are often used to delegate part of the job
 | 
						|
        to child classes:
 | 
						|
<programlisting>
 | 
						|
/* this accessor function is static: it is not exported outside of this file. */
 | 
						|
static void 
 | 
						|
maman_bar_do_specific_action (MamanBar *self, /* parameters */)
 | 
						|
{
 | 
						|
  MAMAN_BAR_GET_CLASS (self)->do_specific_action (self, /* parameters */);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
maman_bar_do_any_action (MamanBar *self, /* parameters */)
 | 
						|
{
 | 
						|
  /* random code here */
 | 
						|
 | 
						|
  /* 
 | 
						|
   * Try to execute the requested action. Maybe the requested action
 | 
						|
   * cannot be implemented here. So, we delegate its implementation
 | 
						|
   * to the child class:
 | 
						|
   */
 | 
						|
  maman_bar_do_specific_action (self, /* parameters */);
 | 
						|
 | 
						|
  /* other random code here */
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
      </para>
 | 
						|
 | 
						|
      <para>
 | 
						|
        Again, it is possible to provide a default implementation for this
 | 
						|
        private virtual class function:
 | 
						|
<programlisting>
 | 
						|
static void
 | 
						|
maman_bar_class_init (MamanBarClass *klass)
 | 
						|
{
 | 
						|
  /* pure virtual method: mandates implementation in children. */
 | 
						|
  klass->do_specific_action_one = NULL;
 | 
						|
 | 
						|
  /* merely virtual method. */
 | 
						|
  klass->do_specific_action_two = maman_bar_real_do_specific_action_two;
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
      </para>
 | 
						|
 | 
						|
      <para>
 | 
						|
        Children can then implement the subclass with code such as:
 | 
						|
<programlisting>
 | 
						|
static void
 | 
						|
maman_bar_subtype_class_init (MamanBarSubTypeClass *klass)
 | 
						|
{
 | 
						|
  MamanBarClass *bar_class = MAMAN_BAR_CLASS (klass);
 | 
						|
 | 
						|
  /* implement pure virtual class function. */
 | 
						|
  bar_class->do_specific_action_one = maman_bar_subtype_do_specific_action_one;
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
      </para>
 | 
						|
    </sect2>
 | 
						|
  </sect1>
 | 
						|
 | 
						|
  <sect1 id="howto-gobject-chainup">
 | 
						|
    <title>Chaining up</title>
 | 
						|
    
 | 
						|
    <para>Chaining up is often loosely defined by the following set of
 | 
						|
    conditions:
 | 
						|
      <itemizedlist>
 | 
						|
        <listitem><para>Parent class A defines a public virtual method named <function>foo</function> and 
 | 
						|
        provides a default implementation.</para></listitem>
 | 
						|
        <listitem><para>Child class B re-implements method <function>foo</function>.</para></listitem>
 | 
						|
        <listitem><para>In the method B::foo, the child class B calls its parent class method A::foo.</para></listitem>
 | 
						|
      </itemizedlist>
 | 
						|
      There are various uses to this idiom:
 | 
						|
      <itemizedlist>
 | 
						|
        <listitem><para>You need to extend the behaviour of a class without modifying its code. You create
 | 
						|
          a subclass to inherit its implementation, re-implement a public virtual method to modify the behaviour
 | 
						|
          and chain up to ensure that the previous behaviour is not really modified, just extended.
 | 
						|
          </para></listitem>
 | 
						|
        <listitem><para>You need to implement the Chain Of Responsibility pattern: each object of the inheritance
 | 
						|
          tree chains up to its parent (typically, at the beginning or the end of the method) to ensure that
 | 
						|
          they each handler is run in turn.</para></listitem>
 | 
						|
      </itemizedlist>
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      To explicitly chain up to the implementation of the virtual method in the parent class, 
 | 
						|
      you first need a handle to the original parent class structure. This pointer can then be used to 
 | 
						|
      access the original class function pointer and invoke it directly.
 | 
						|
      <footnote>
 | 
						|
        <para>
 | 
						|
          The <emphasis>original</emphasis> adjective used in this sentence is not innocuous. To fully 
 | 
						|
          understand its meaning, you need to recall how class structures are initialized: for each object type,
 | 
						|
          the class structure associated to this object is created by first copying the class structure of its 
 | 
						|
          parent type (a simple <function>memcpy</function>) and then by invoking the class_init callback on 
 | 
						|
          the resulting class structure. Since the class_init callback is responsible for overwriting the class structure
 | 
						|
          with the user re-implementations of the class methods, we cannot merely use the modified copy of the parent class
 | 
						|
          structure stored in our derived instance. We want to get a copy of the class structure of an instance of the parent 
 | 
						|
          class.
 | 
						|
        </para>
 | 
						|
      </footnote>
 | 
						|
    </para>
 | 
						|
    
 | 
						|
    <para>The function <function><link linkend="g-type-class-peek-parent">g_type_class_peek_parent</link></function>
 | 
						|
    is used to access the original parent class structure. Its input is a
 | 
						|
    pointer to the class of the derived object and it returns a pointer to
 | 
						|
    the original parent class structure. Instead of using this function
 | 
						|
    directly, though, you should use the <function>parent_class</function>
 | 
						|
    pointer created and initialized for us by the G_DEFINE_TYPE_* family of
 | 
						|
    macros, for instance:
 | 
						|
<programlisting>
 | 
						|
static void
 | 
						|
b_method_to_call (B *obj, int a)
 | 
						|
{
 | 
						|
  /* do stuff before chain up */
 | 
						|
 | 
						|
  /* call the method_to_call() virtual function on the
 | 
						|
   * parent of BClass, AClass.
 | 
						|
   *
 | 
						|
   * remember the explicit cast to AClass*
 | 
						|
   */
 | 
						|
  A_CLASS (b_parent_class)->method_to_call (obj, a);
 | 
						|
 | 
						|
  /* do stuff after chain up */
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
  </para>
 | 
						|
 | 
						|
  </sect1>
 | 
						|
 | 
						|
</chapter>
 | 
						|
<!-- End Howto GObject -->
 | 
						|
 | 
						|
<chapter id="howto-interface">
 | 
						|
  <title>How to define and implement interfaces</title>
 | 
						|
 | 
						|
  <sect1 id="howto-interface-define">
 | 
						|
    <title>Defining interfaces</title>
 | 
						|
  
 | 
						|
  <para>
 | 
						|
    The bulk of interface definition has already been shown in <xref linkend="gtype-non-instantiable-classed"/>
 | 
						|
    but I feel it is needed to show exactly how to create an interface.
 | 
						|
  </para>
 | 
						|
 | 
						|
  <para>
 | 
						|
    As above, the first step is to get the header right. This interface
 | 
						|
    defines two methods:
 | 
						|
<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);
 | 
						|
  void (*do_something) (MamanIbaz *self);
 | 
						|
};
 | 
						|
 | 
						|
GType maman_ibaz_get_type (void);
 | 
						|
 | 
						|
void maman_ibaz_do_action    (MamanIbaz *self);
 | 
						|
void maman_ibaz_do_something (MamanIbaz *self);
 | 
						|
 | 
						|
#endif /* __MAMAN_IBAZ_H__ */
 | 
						|
</programlisting>
 | 
						|
    This code is the same as the code for a normal <link linkend="GType"><type>GType</type></link>
 | 
						|
    which derives from a <link linkend="GObject"><type>GObject</type></link> except for a few details:
 | 
						|
    <itemizedlist>
 | 
						|
      <listitem><para>
 | 
						|
        The <function>_GET_CLASS</function> macro is called <function>_GET_INTERFACE</function>
 | 
						|
                  and not implemented with <function><link linkend="G-TYPE-INSTANCE-GET-CLASS:CAPS">G_TYPE_INSTANCE_GET_CLASS</link></function>
 | 
						|
                  but with <function><link linkend="G-TYPE-INSTANCE-GET-INTERFACE:CAPS">G_TYPE_INSTANCE_GET_INTERFACE</link></function>.
 | 
						|
      </para></listitem>
 | 
						|
      <listitem><para>
 | 
						|
        The instance type, <type>MamanIbaz</type> is not fully defined: it is
 | 
						|
        used merely as an abstract type which represents an instance of
 | 
						|
        whatever object which implements the interface.
 | 
						|
      </para></listitem>
 | 
						|
      <listitem><para>
 | 
						|
        The parent of the <type>MamanIbazInterface</type> is not
 | 
						|
        <type>GObjectClass</type> but <type>GTypeInterface</type>.
 | 
						|
      </para></listitem>
 | 
						|
    </itemizedlist>
 | 
						|
  </para>
 | 
						|
 | 
						|
  <para>
 | 
						|
    The implementation of the <type>MamanIbaz</type> type itself is trivial:
 | 
						|
    <itemizedlist>
 | 
						|
      <listitem><para><function><link linkend="G-DEFINE-INTERFACE:CAPS">G_DEFINE_INTERFACE</link></function>
 | 
						|
       creates a <function>maman_ibaz_get_type</function> function which registers the
 | 
						|
       type in the type system. The third argument is used to define a
 | 
						|
       <link linkend="howto-interface-prerequisite">prerequisite interface</link>
 | 
						|
       (which we'll talk about more later). Just pass <code>0</code> for this
 | 
						|
       argument when an interface has no prerequisite.
 | 
						|
       </para></listitem>
 | 
						|
      <listitem><para><function>maman_ibaz_default_init</function> is expected
 | 
						|
      to register the interface's signals if there are any (we will see a bit
 | 
						|
      later how to use them).</para></listitem>
 | 
						|
      <listitem><para>The interface methods <function>maman_ibaz_do_action</function>
 | 
						|
      and <function>maman_ibaz_do_something</function> dereference the interface
 | 
						|
      structure to access its associated interface function and call it.
 | 
						|
      </para></listitem>
 | 
						|
    </itemizedlist>
 | 
						|
<programlisting>
 | 
						|
G_DEFINE_INTERFACE (MamanIbaz, maman_ibaz, 0);
 | 
						|
 | 
						|
static void
 | 
						|
maman_ibaz_default_init (gpointer g_class)
 | 
						|
{
 | 
						|
    /* 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_INTERFACE (self)->do_action (self);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
maman_ibaz_do_something (MamanIbaz *self)
 | 
						|
{
 | 
						|
  g_return_if_fail (MAMAN_IS_IBAZ (self));
 | 
						|
 | 
						|
  MAMAN_IBAZ_GET_INTERFACE (self)->do_something (self);
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
    </para>
 | 
						|
  </sect1>
 | 
						|
  
 | 
						|
  <sect1 id="howto-interface-implement">
 | 
						|
    <title>Implementing interfaces</title>
 | 
						|
  
 | 
						|
    <para>
 | 
						|
      Once the interface is defined, implementing it is rather trivial.
 | 
						|
    </para>
 | 
						|
  
 | 
						|
    <para>
 | 
						|
      The first step is to define a normal GObject class, like:
 | 
						|
<programlisting>
 | 
						|
#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_IS_BAZ(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_TYPE_BAZ))
 | 
						|
#define MAMAN_BAZ_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), MAMAN_TYPE_BAZ, MamanbazClass))
 | 
						|
#define MAMAN_IS_BAZ_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), MAMAN_TYPE_BAZ))
 | 
						|
#define MAMAN_BAZ_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), MAMAN_TYPE_BAZ, MamanbazClass))
 | 
						|
 | 
						|
 | 
						|
typedef struct _MamanBaz        MamanBaz;
 | 
						|
typedef struct _MamanBazClass   MamanBazClass;
 | 
						|
 | 
						|
struct _MamanBaz
 | 
						|
{
 | 
						|
  GObject parent_instance;
 | 
						|
 | 
						|
  gint instance_member;
 | 
						|
};
 | 
						|
 | 
						|
struct _MamanBazClass
 | 
						|
{
 | 
						|
  GObjectClass parent_class;
 | 
						|
};
 | 
						|
 | 
						|
GType maman_baz_get_type (void);
 | 
						|
 | 
						|
#endif /* __MAMAN_BAZ_H__ */
 | 
						|
</programlisting>
 | 
						|
      <!-- Ha ha! "nothing weird or scary". I actually laughed out loud. Oh boy.
 | 
						|
           The fact that we're so intimate with GObject that all this doesn't look
 | 
						|
           wierd, that's the scary thing. :) -->
 | 
						|
      There is clearly nothing specifically weird or scary about this header:
 | 
						|
      it does not define any weird API or derive from a weird type.
 | 
						|
    </para>
 | 
						|
  
 | 
						|
    <para>
 | 
						|
      The second step is to implement <type>MamanBaz</type> by defining
 | 
						|
      its GType. Instead of using
 | 
						|
      <function><link linkend="G-DEFINE-TYPE:CAPS">G_DEFINE_TYPE</link></function>
 | 
						|
      we use
 | 
						|
      <function><link linkend="G-DEFINE-TYPE-WITH-CODE:CAPS">G_DEFINE_TYPE_WITH_CODE</link></function>
 | 
						|
      and the
 | 
						|
      <function><link linkend="G-IMPLEMENT-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function>
 | 
						|
      macros.
 | 
						|
<programlisting>
 | 
						|
static void maman_ibaz_interface_init (MamanIbazInterface *iface);
 | 
						|
 | 
						|
G_DEFINE_TYPE_WITH_CODE (MamanBar, maman_bar, G_TYPE_OBJECT,
 | 
						|
                         G_IMPLEMENT_INTERFACE (MAMAN_TYPE_IBAZ,
 | 
						|
                                                maman_ibaz_interface_init))
 | 
						|
</programlisting>
 | 
						|
      This definition is very much like all the similar functions we looked
 | 
						|
      at previously. The only interface-specific code present here is the call to
 | 
						|
      <function><link linkend="G-IMPLEMENT-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function>.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <note><para>Classes can implement multiple interfaces by using multiple calls to
 | 
						|
    <function><link linkend="G-IMPLEMENT-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function>
 | 
						|
    inside the call to
 | 
						|
    <function><link linkend="G-DEFINE-TYPE-WITH-CODE:CAPS">G_DEFINE_TYPE_WITH_CODE</link></function>
 | 
						|
    </para></note>
 | 
						|
  
 | 
						|
    <para>
 | 
						|
      <function>maman_baz_interface_init</function>, the interface
 | 
						|
      initialization function: inside it every virtual method of the interface
 | 
						|
      must be assigned to its implementation:
 | 
						|
<programlisting>
 | 
						|
static void
 | 
						|
maman_baz_do_action (MamanBaz *self)
 | 
						|
{
 | 
						|
  g_print ("Baz implementation of Ibaz interface Action: 0x%x.\n",
 | 
						|
           self->instance_member);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_baz_do_something (MamanBaz *self)
 | 
						|
{
 | 
						|
  g_print ("Baz implementation of Ibaz interface Something: 0x%x.\n",
 | 
						|
           self->instance_member);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_ibaz_interface_init (MamanIbazInterface *iface)
 | 
						|
{
 | 
						|
  iface->do_action = maman_baz_do_action;
 | 
						|
  iface->do_something = maman_baz_do_something;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_baz_init (MamanBaz *self)
 | 
						|
{
 | 
						|
  MamanBaz *self = MAMAN_BAZ (instance);
 | 
						|
  self->instance_member = 0xdeadbeaf;
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
    </para>
 | 
						|
  </sect1>
 | 
						|
  
 | 
						|
  <sect1 id="howto-interface-prerequisite">
 | 
						|
    <title>Interface definition prerequisites</title>
 | 
						|
  
 | 
						|
    <para>
 | 
						|
      To specify that an interface requires the presence of other interfaces
 | 
						|
      when implemented, GObject introduces the concept of
 | 
						|
      <emphasis>prerequisites</emphasis>: it is possible to associate
 | 
						|
      a list of prerequisite types to an interface. For example, if
 | 
						|
      object A wishes to implement interface I1, and if interface I1 has a
 | 
						|
      prerequisite on interface I2, A has to implement both I1 and I2.
 | 
						|
    </para>
 | 
						|
  
 | 
						|
    <para>
 | 
						|
      The mechanism described above is, in practice, very similar to
 | 
						|
      Java's interface I1 extends interface I2. The example below shows
 | 
						|
      the GObject equivalent:
 | 
						|
<programlisting>
 | 
						|
/* Make the MamanIbar interface require MamanIbaz interface. */
 | 
						|
G_DEFINE_INTERFACE (MamanIbar, maman_ibar, MAMAN_TYPE_IBAZ);
 | 
						|
</programlisting>
 | 
						|
      In the <function><link linkend="G-DEFINE-INTERFACE:CAPS">G_DEFINE_INTERFACE</link></function>
 | 
						|
      call above, the third parameter defines the prerequisite type. This
 | 
						|
      is the GType of either an interface or a class. In this case
 | 
						|
      the MamanIbaz interface is a prerequisite of the MamanIbar. The code
 | 
						|
      below shows how an implementation can implement both interfaces and
 | 
						|
      register their implementations:
 | 
						|
<programlisting>
 | 
						|
static void
 | 
						|
maman_ibar_do_another_action (MamanIbar *ibar)
 | 
						|
{
 | 
						|
  MamanBar *self = MAMAN_BAR (ibar);
 | 
						|
 | 
						|
  g_print ("Bar implementation of IBar interface Another Action: 0x%x.\n",
 | 
						|
           self->instance_member);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_ibar_interface_init (MamanIbarInterface *iface)
 | 
						|
{
 | 
						|
  iface->do_another_action = maman_ibar_do_another_action;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_ibaz_do_action (MamanIbaz *ibaz)
 | 
						|
{
 | 
						|
  MamanBar *self = MAMAN_BAR (ibaz);
 | 
						|
 | 
						|
  g_print ("Bar implementation of Ibaz interface Action: 0x%x.\n",
 | 
						|
           self->instance_member);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_ibaz_do_something (MamanIbaz *ibaz)
 | 
						|
{
 | 
						|
  MamanBar *self = MAMAN_BAR (ibaz);
 | 
						|
 | 
						|
  g_print ("Bar implementation of Ibaz interface Something: 0x%x.\n",
 | 
						|
           self->instance_member);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_ibaz_interface_init (MamanIbazInterface *iface)
 | 
						|
{
 | 
						|
  iface->do_action = maman_ibaz_do_action;
 | 
						|
  iface->do_something = maman_ibaz_do_something;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_bar_class_init (MamanBarClass *klass)
 | 
						|
{
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_bar_init (MamanBar *self)
 | 
						|
{
 | 
						|
  self->instance_member = 0x666;
 | 
						|
}
 | 
						|
 | 
						|
G_DEFINE_TYPE_WITH_CODE (MamanBar, maman_bar, G_TYPE_OBJECT,
 | 
						|
                         G_IMPLEMENT_INTERFACE (MAMAN_TYPE_IBAZ,
 | 
						|
                                                maman_ibaz_interface_init)
 | 
						|
                         G_IMPLEMENT_INTERFACE (MAMAN_TYPE_IBAR,
 | 
						|
                                                maman_ibar_interface_init))
 | 
						|
</programlisting>
 | 
						|
      It is very important to notice that the order in which interface
 | 
						|
      implementations are added to the main object is not random:
 | 
						|
      <function><link linkend="g-type-add-interface-static">g_type_add_interface_static</link></function>,
 | 
						|
      which is called by
 | 
						|
      <function><link linkend="G-DEFINE-INTERFACE:CAPS">G_IMPLEMENT_INTERFACE</link></function>,
 | 
						|
      must be invoked first on the interfaces which have no prerequisites and then on
 | 
						|
      the others.
 | 
						|
    </para>
 | 
						|
  </sect1>
 | 
						|
  
 | 
						|
  <sect1 id="howto-interface-properties">
 | 
						|
    <title>Interface properties</title>
 | 
						|
  
 | 
						|
    <para>
 | 
						|
      GObject interfaces can also have
 | 
						|
      properties. Declaration of the interface properties is similar to
 | 
						|
      declaring the properties of ordinary GObject types as explained in
 | 
						|
      <xref linkend="gobject-properties"/>, except that
 | 
						|
      <function><link linkend="g-object-interface-install-property">g_object_interface_install_property</link></function>
 | 
						|
      is used to declare the properties instead of
 | 
						|
      <function><link linkend="g-object-class-install-property">g_object_class_install_property</link></function>.
 | 
						|
    </para>
 | 
						|
  
 | 
						|
    <para>
 | 
						|
      To include a property named 'name' of type <type>string</type> in the 
 | 
						|
      <type>maman_ibaz</type> interface example code above, we only need to
 | 
						|
      add one 
 | 
						|
      <footnote>
 | 
						|
        <para>
 | 
						|
          That really is one line extended to six for the sake of clarity
 | 
						|
        </para>
 | 
						|
      </footnote>  
 | 
						|
      line in the <function>maman_ibaz_default_init</function> as shown below:
 | 
						|
<programlisting>
 | 
						|
static void
 | 
						|
maman_ibaz_default_init (gpointer g_iface)
 | 
						|
{
 | 
						|
  g_object_interface_install_property (g_iface,
 | 
						|
                                       g_param_spec_string ("name",
 | 
						|
                                                            "Name",
 | 
						|
                                                            "Name of the MamanIbaz",
 | 
						|
                                                            "maman",
 | 
						|
                                                            G_PARAM_READWRITE));
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
    </para>
 | 
						|
  
 | 
						|
    <para>
 | 
						|
      One point worth noting is that the declared property wasn't assigned an 
 | 
						|
      integer ID. The reason being that integer IDs of properties are used
 | 
						|
      only inside the get and set methods and since interfaces do not
 | 
						|
      implement properties, there is no need to assign integer IDs to
 | 
						|
      interface properties.
 | 
						|
    </para>
 | 
						|
    
 | 
						|
    <para>
 | 
						|
      An implementation declares and defines it's properties in the usual
 | 
						|
      way as explained in <xref linkend="gobject-properties"/>, except for one
 | 
						|
      small change: it can declare the properties of the interface it
 | 
						|
      implements using <function><link linkend="g-object-class-override-property">g_object_class_override_property</link></function>
 | 
						|
      instead of <function><link linkend="g-object-class-install-property">g_object_class_install_property</link></function>.
 | 
						|
      The following code snippet shows the modifications needed in the
 | 
						|
      <type>MamanBaz</type> declaration and implementation above:
 | 
						|
<programlisting>
 | 
						|
 | 
						|
struct _MamanBaz
 | 
						|
{
 | 
						|
  GObject parent_instance;
 | 
						|
 | 
						|
  gint instance_member;
 | 
						|
  gchar *name;
 | 
						|
};
 | 
						|
 | 
						|
enum
 | 
						|
{
 | 
						|
  PROP_0,
 | 
						|
  PROP_NAME
 | 
						|
};
 | 
						|
 | 
						|
static void
 | 
						|
maman_baz_set_property (GObject      *object,
 | 
						|
                        guint         prop_id,
 | 
						|
                        const GValue *value,
 | 
						|
                        GParamSpec   *pspec)
 | 
						|
{
 | 
						|
  MamanBaz *baz = MAMAN_BAZ (object);
 | 
						|
 | 
						|
  switch (prop_id)
 | 
						|
    {
 | 
						|
    case PROP_NAME:
 | 
						|
      g_free (baz->name);
 | 
						|
      baz->name = g_value_dup_string (value);
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_baz_get_property (GObject    *object,
 | 
						|
                        guint       prop_id,
 | 
						|
                        GValue     *value,
 | 
						|
                        GParamSpec *pspec)
 | 
						|
{
 | 
						|
  MamanBaz *baz = MAMAN_BAZ (object);
 | 
						|
 | 
						|
  switch (prop_id)
 | 
						|
    {
 | 
						|
    case PROP_NAME:
 | 
						|
      g_value_set_string (value, baz->name);
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_baz_class_init (MamanBazClass *klass)
 | 
						|
{
 | 
						|
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 | 
						|
 | 
						|
  gobject_class->set_property = maman_baz_set_property;
 | 
						|
  gobject_class->get_property = maman_baz_get_property;
 | 
						|
 | 
						|
  g_object_class_override_property (gobject_class, PROP_NAME, "name");
 | 
						|
}
 | 
						|
 | 
						|
</programlisting>
 | 
						|
    </para>
 | 
						|
  
 | 
						|
  </sect1>
 | 
						|
 | 
						|
  <sect1 id="howto-interface-override">
 | 
						|
    <title>Overriding interface methods</title>
 | 
						|
 | 
						|
    <para>
 | 
						|
      If a base class already implements an interface, and in a derived
 | 
						|
      class you wish to implement the same interface overriding only certain
 | 
						|
      methods of that interface, you just reimplement the interface and
 | 
						|
      set only the interface methods you wish to override.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      In this example MamanDerivedBaz is derived from MamanBaz. Both
 | 
						|
      implement the MamanIbaz interface. MamanDerivedBaz only implements one
 | 
						|
      method of the MamanIbaz interface and uses the base class implementation
 | 
						|
      of the other.
 | 
						|
<programlisting>
 | 
						|
static void
 | 
						|
maman_derived_ibaz_do_action (MamanIbaz *ibaz)
 | 
						|
{
 | 
						|
  MamanDerivedBaz *self = MAMAN_DERIVED_BAZ (ibaz);
 | 
						|
  g_print ("DerivedBaz implementation of Ibaz interface Action\n");
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_derived_ibaz_interface_init (MamanIbazInterface *iface)
 | 
						|
{
 | 
						|
  /* Override the implementation of do_action */
 | 
						|
  iface->do_action = maman_derived_ibaz_do_action;
 | 
						|
 | 
						|
  /*
 | 
						|
   * We simply leave iface->do_something alone, it is already set to the
 | 
						|
   * base class implementation.
 | 
						|
   */
 | 
						|
}
 | 
						|
 | 
						|
G_DEFINE_TYPE_WITH_CODE (MamanDerivedBaz, maman_derived_baz, MAMAN_TYPE_BAZ,
 | 
						|
                         G_IMPLEMENT_INTERFACE (MAMAN_TYPE_IBAZ,
 | 
						|
                                                maman_derived_ibaz_interface_init)
 | 
						|
 | 
						|
static void
 | 
						|
maman_derived_baz_class_init (MamanDerivedBazClass *klass)
 | 
						|
{
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_derived_baz_init (MamanDerivedBaz *self)
 | 
						|
{
 | 
						|
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      To access the base class interface implementation use
 | 
						|
      <function><link linkend="g-type-interface-peek-parent">g_type_interface_peek_parent</link></function>
 | 
						|
      from within an interface's <function>default_init</function> function.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      If you wish to call the base class implementation of an interface
 | 
						|
      method from an derived class where than interface method has been
 | 
						|
      overridden then you can stash away the pointer returned from
 | 
						|
      <function><link linkend="g-type-interface-peek-parent">g_type_interface_peek_parent</link></function>
 | 
						|
      in a global variable.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      In this example MamanDerivedBaz overides the
 | 
						|
      <function>do_action</function> interface method. In it's overridden method
 | 
						|
      it calls the base class implementation of the same interface method.
 | 
						|
<programlisting>
 | 
						|
static MamanIbazInterface *maman_ibaz_parent_interface = NULL;
 | 
						|
 | 
						|
static void
 | 
						|
maman_derived_ibaz_do_action (MamanIbaz *ibaz)
 | 
						|
{
 | 
						|
  MamanDerivedBaz *self = MAMAN_DERIVED_BAZ (ibaz);
 | 
						|
  g_print ("DerivedBaz implementation of Ibaz interface Action\n");
 | 
						|
 | 
						|
  /* Now we call the base implementation */
 | 
						|
  maman_ibaz_parent_interface->do_action (ibaz);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_derived_ibaz_interface_init (MamanIbazInterface *iface)
 | 
						|
{
 | 
						|
  maman_ibaz_parent_interface = g_type_interface_peek_parent (iface);
 | 
						|
  iface->do_action = maman_derived_ibaz_do_action;
 | 
						|
}
 | 
						|
 | 
						|
G_DEFINE_TYPE_WITH_CODE (MamanDerivedBaz, maman_derived_baz, MAMAN_TYPE_BAZ,
 | 
						|
                         G_IMPLEMENT_INTERFACE (MAMAN_TYPE_IBAZ,
 | 
						|
                                                maman_derived_ibaz_interface_init))
 | 
						|
 | 
						|
static void
 | 
						|
maman_derived_baz_class_init (MamanDerivedBazClass *klass)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
maman_derived_baz_init (MamanDerivedBaz *self)
 | 
						|
{
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
    </para>
 | 
						|
 | 
						|
  </sect1>
 | 
						|
 | 
						|
</chapter>
 | 
						|
<!-- End Howto Interfaces -->
 | 
						|
 | 
						|
<chapter id="howto-signals">
 | 
						|
  <title>How to create and use signals</title>
 | 
						|
 | 
						|
  <para>
 | 
						|
    The signal system which was built in GType is pretty complex and
 | 
						|
    flexible: it is possible for its users to connect at runtime any
 | 
						|
    number of callbacks (implemented in any language for which a binding
 | 
						|
    exists)
 | 
						|
    <footnote>
 | 
						|
      <para>A Python callback can be connected to any signal on any
 | 
						|
      C-based GObject, and vice versa, assuming that the Python object
 | 
						|
      inherits from GObject.</para>
 | 
						|
    </footnote>
 | 
						|
    to any signal and to stop the emission of any signal at any 
 | 
						|
    state of the signal emission process. This flexibility makes it
 | 
						|
    possible to use GSignal for much more than just emit signals which
 | 
						|
    can be received by numerous clients. 
 | 
						|
  </para>
 | 
						|
 | 
						|
  <sect1 id="howto-simple-signals">
 | 
						|
    <title>Simple use of signals</title>
 | 
						|
 | 
						|
    <para>
 | 
						|
      The most basic use of signals is to implement simple event
 | 
						|
      notification: for example, if we have a MamanFile object, and
 | 
						|
      if this object has a write method, we might wish to be notified
 | 
						|
      whenever someone has changed something via our MamanFile instance.
 | 
						|
      The code below shows how the user can connect a callback to the
 | 
						|
      "changed" signal.
 | 
						|
<programlisting>
 | 
						|
file = g_object_new (MAMAN_FILE_TYPE, NULL);
 | 
						|
 | 
						|
g_signal_connect (file, "changed", G_CALLBACK (changed_event), NULL);
 | 
						|
 | 
						|
maman_file_write (file, buffer, strlen (buffer));
 | 
						|
</programlisting>
 | 
						|
    </para>
 | 
						|
    
 | 
						|
    <para>
 | 
						|
      The <type>MamanFile</type> signal is registered in the class_init
 | 
						|
      function:
 | 
						|
<programlisting>
 | 
						|
file_signals[CHANGED] = 
 | 
						|
  g_signal_newv ("changed",
 | 
						|
                 G_TYPE_FROM_CLASS (gobject_class),
 | 
						|
                 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
 | 
						|
                 NULL /* closure */,
 | 
						|
                 NULL /* accumulator */,
 | 
						|
                 NULL /* accumulator data */,
 | 
						|
                 g_cclosure_marshal_VOID__VOID,
 | 
						|
                 G_TYPE_NONE /* return_type */,
 | 
						|
                 0     /* n_params */,
 | 
						|
                 NULL  /* param_types */);
 | 
						|
</programlisting>
 | 
						|
      and the signal is emitted in <function>maman_file_write</function>:
 | 
						|
<programlisting>
 | 
						|
void
 | 
						|
maman_file_write (MamanFile    *self,
 | 
						|
                  const guchar *buffer,
 | 
						|
                  gssize        size)
 | 
						|
{
 | 
						|
  /* First write data. */
 | 
						|
 | 
						|
  /* Then, notify user of data written. */
 | 
						|
  g_signal_emit (self, file_signals[CHANGED], 0 /* details */);
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
      As shown above, you can safely set the details parameter to zero if
 | 
						|
      you do not know what it can be used for. For a discussion of what you
 | 
						|
      could used it for, see <xref linkend="signal-detail"/>
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      The signature of the signal handler in the above example is defined as
 | 
						|
      <function>g_cclosure_marshal_VOID__VOID</function>. Its name follows
 | 
						|
      a simple convention which encodes the function parameter and return value
 | 
						|
      types in the function name. Specifically, the value in front of the
 | 
						|
      double underscore is the type of the return value, while the value(s)
 | 
						|
      after the double underscore denote the parameter types.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      The header <filename>gobject/gmarshal.h</filename> defines a set of
 | 
						|
      commonly needed closures that one can use. If you want to have complex
 | 
						|
      marshallers for your signals you should probably use glib-genmarshal
 | 
						|
      to autogenerate them from a file containing their return and
 | 
						|
      parameter types.
 | 
						|
    </para>
 | 
						|
  </sect1>
 | 
						|
 | 
						|
<!-- 
 | 
						|
  this is utterly wrong and should be completely removed - or rewritten
 | 
						|
  with a better example than writing a buffer using synchronous signals.
 | 
						|
 | 
						|
  <sect1>
 | 
						|
    <title>How to provide more flexibility to users?</title>
 | 
						|
 | 
						|
    <para>
 | 
						|
      The previous implementation does the job but the signal facility of
 | 
						|
      GObject can be used to provide even more flexibility to this file
 | 
						|
      change notification mechanism. One of the key ideas is to make the
 | 
						|
      process of writing data to the file part of the signal emission
 | 
						|
      process to allow users to be notified either before or after the
 | 
						|
      data is written to the file.
 | 
						|
    </para>
 | 
						|
    
 | 
						|
    <para>
 | 
						|
      To integrate the process of writing the data to the file into the
 | 
						|
      signal emission mechanism, we can register a default class closure
 | 
						|
      for this signal which will be invoked during the signal emission,
 | 
						|
      just like any other user-connected signal handler. 
 | 
						|
    </para>
 | 
						|
    
 | 
						|
    <para>
 | 
						|
      The first step to implement this idea is to change the signature of
 | 
						|
      the signal: we need to pass around the buffer to write and its size.
 | 
						|
      To do this, we use our own marshaller which will be generated
 | 
						|
      through GLib's glib-genmarshal tool. We thus create a file named <filename>marshall.list</filename> which contains
 | 
						|
      the following single line:
 | 
						|
<programlisting>
 | 
						|
VOID:POINTER,UINT
 | 
						|
</programlisting>
 | 
						|
      and use the Makefile provided in <filename>sample/signal/Makefile</filename> to generate the file named
 | 
						|
      <filename>maman-file-complex-marshall.c</filename>. This C file is finally included in 
 | 
						|
      <filename>maman-file-complex.c</filename>.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      Once the marshaller is present, we register the signal and its marshaller in the class_init function 
 | 
						|
      of the object <type>MamanFileComplex</type> (full source for this object is included in 
 | 
						|
      <filename>sample/signal/maman-file-complex.{h|c}</filename>):
 | 
						|
<programlisting>
 | 
						|
GClosure *default_closure;
 | 
						|
GType param_types[2];
 | 
						|
 | 
						|
default_closure = g_cclosure_new (G_CALLBACK (default_write_signal_handler),
 | 
						|
                                  (gpointer)0xdeadbeaf /* user_data */, 
 | 
						|
                                  NULL /* destroy_data */);
 | 
						|
 | 
						|
param_types[0] = G_TYPE_POINTER;
 | 
						|
param_types[1] = G_TYPE_UINT;
 | 
						|
klass->write_signal_id = 
 | 
						|
  g_signal_newv ("write",
 | 
						|
                 G_TYPE_FROM_CLASS (g_class),
 | 
						|
                 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
 | 
						|
                 default_closure /* class closure */,
 | 
						|
                 NULL /* accumulator */,
 | 
						|
                 NULL /* accu_data */,
 | 
						|
                 maman_file_complex_VOID__POINTER_UINT,
 | 
						|
                 G_TYPE_NONE /* return_type */,
 | 
						|
                 2     /* n_params */,
 | 
						|
                 param_types /* param_types */);
 | 
						|
</programlisting>
 | 
						|
      The code shown above first creates the closure which contains the code to complete the file write. This
 | 
						|
      closure is registered as the default class_closure of the newly created signal.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      Of course, you need to implement completely the code for the default closure since I just provided
 | 
						|
      a skeleton:
 | 
						|
<programlisting>
 | 
						|
static void
 | 
						|
default_write_signal_handler (GObject *obj, guint8 *buffer, guint size, gpointer user_data)
 | 
						|
{
 | 
						|
  g_assert (user_data == (gpointer)0xdeadbeaf);
 | 
						|
  /* Here, we trigger the real file write. */
 | 
						|
  g_print ("default signal handler: 0x%x %u\n", buffer, size);
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      Finally, the client code must invoke the <function>maman_file_complex_write</function> function which 
 | 
						|
      triggers the signal emission:
 | 
						|
<programlisting>
 | 
						|
void maman_file_complex_write (MamanFileComplex *self, guint8 *buffer, guint size)
 | 
						|
{
 | 
						|
  /* trigger event */
 | 
						|
  g_signal_emit (self,
 | 
						|
                 MAMAN_FILE_COMPLEX_GET_CLASS (self)->write_signal_id,
 | 
						|
                 0, /* details */
 | 
						|
                 buffer, size);
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
    </para>
 | 
						|
    
 | 
						|
    <para>
 | 
						|
      The client code (as shown in <filename>sample/signal/test.c</filename> and below) can now connect signal handlers before 
 | 
						|
      and after the file write is completed: since the default signal handler which does the write itself runs during the 
 | 
						|
      RUN_LAST phase of the signal emission, it will run after all handlers connected with <function><link linkend="g-signal-connect">g_signal_connect</link></function>
 | 
						|
      and before all handlers connected with <function><link linkend="g-signal-connect-after">g_signal_connect_after</link></function>. If you intent to write a GObject
 | 
						|
      which emits signals, I would thus urge you to create all your signals with the G_SIGNAL_RUN_LAST such that your users
 | 
						|
      have a maximum of flexibility as to when to get the event. Here, we combined it with G_SIGNAL_NO_RECURSE and 
 | 
						|
      G_SIGNAL_NO_HOOKS to ensure our users will not try to do really weird things with our GObject. I strongly advise you
 | 
						|
      to do the same unless you really know why (in which case you really know the inner workings of GSignal by heart and
 | 
						|
      you are not reading this).
 | 
						|
    </para>
 | 
						|
    
 | 
						|
    <para>
 | 
						|
<programlisting>
 | 
						|
static void complex_write_event_before (GObject *file, guint8 *buffer, guint size, gpointer user_data)
 | 
						|
{
 | 
						|
  g_assert (user_data == NULL);
 | 
						|
  g_print ("Complex Write event before: 0x%x, %u\n", buffer, size);
 | 
						|
}
 | 
						|
 | 
						|
static void complex_write_event_after (GObject *file, guint8 *buffer, guint size, gpointer user_data)
 | 
						|
{
 | 
						|
  g_assert (user_data == NULL);
 | 
						|
  g_print ("Complex Write event after: 0x%x, %u\n", buffer, size);
 | 
						|
}
 | 
						|
 | 
						|
static void test_file_complex (void)
 | 
						|
{
 | 
						|
  guint8 buffer[100];
 | 
						|
  GObject *file;
 | 
						|
 | 
						|
  file = g_object_new (MAMAN_FILE_COMPLEX_TYPE, NULL);
 | 
						|
 | 
						|
  g_signal_connect (G_OBJECT (file), "write",
 | 
						|
                    (GCallback)complex_write_event_before,
 | 
						|
                    NULL);
 | 
						|
 | 
						|
  g_signal_connect_after (G_OBJECT (file), "write",
 | 
						|
                          (GCallback)complex_write_event_after,
 | 
						|
                          NULL);
 | 
						|
 | 
						|
  maman_file_complex_write (MAMAN_FILE_COMPLEX (file), buffer, 50);
 | 
						|
 | 
						|
  g_object_unref (G_OBJECT (file));
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
      The code above generates the following output on my machine:
 | 
						|
<programlisting>
 | 
						|
Complex Write event before: 0xbfffe280, 50
 | 
						|
default signal handler: 0xbfffe280 50
 | 
						|
Complex Write event after: 0xbfffe280, 50
 | 
						|
</programlisting>
 | 
						|
    </para>
 | 
						|
 | 
						|
-->
 | 
						|
 | 
						|
<!--
 | 
						|
  this is also utterly wrong on so many levels that I don't even want
 | 
						|
  to enumerate them. it's also full of completely irrelevant footnotes
 | 
						|
  about personal preferences demonstrating a severe lack of whatsoever
 | 
						|
  clue. the whole idea of storing the signal ids inside the Class
 | 
						|
  structure is so fundamentally flawed that I'll require a frontal
 | 
						|
  lobotomy just to forget I've ever seen it.
 | 
						|
 | 
						|
    <sect2>
 | 
						|
    <title>How most people do the same thing with less code</title>
 | 
						|
    
 | 
						|
      <para>For many historic reasons related to how the ancestor of GObject used to work in GTK+ 1.x versions,
 | 
						|
        there is a much <emphasis>simpler</emphasis> 
 | 
						|
        <footnote>
 | 
						|
          <para>I personally think that this method is horribly mind-twisting: it adds a new indirection
 | 
						|
          which unnecessarily complicates the overall code path. However, because this method is widely used
 | 
						|
          by all of GTK+ and GObject code, readers need to understand it. The reason why this is done that way
 | 
						|
          in most of GTK+ is related to the fact that the ancestor of GObject did not provide any other way to
 | 
						|
          create a signal with a default handler than this one. Some people have tried to justify that it is done
 | 
						|
          that way because it is better, faster (I am extremely doubtful about the faster bit. As a matter of fact,
 | 
						|
          the better bit also mystifies me ;-). I have the feeling no one really knows and everyone does it
 | 
						|
          because they copy/pasted code from code which did the same. It is probably better to leave this 
 | 
						|
          specific trivia to hacker legends domain...
 | 
						|
          </para>
 | 
						|
        </footnote>
 | 
						|
        way to create a signal with a default handler than to create 
 | 
						|
        a closure by hand and to use the <function><link linkend="g-signal-newv">g_signal_newv</link></function>.
 | 
						|
      </para>
 | 
						|
    
 | 
						|
      <para>For example, <function><link linkend="g-signal-new">g_signal_new</link></function> can be used to create a signal which uses a default 
 | 
						|
        handler which is stored in the class structure of the object. More specifically, the class structure 
 | 
						|
        contains a function pointer which is accessed during signal emission to invoke the default handler and
 | 
						|
        the user is expected to provide to <function><link linkend="g-signal-new">g_signal_new</link></function> the offset from the start of the
 | 
						|
        class structure to the function pointer.
 | 
						|
          <footnote>
 | 
						|
            <para>I would like to point out here that the reason why the default handler of a signal is named everywhere
 | 
						|
             a class_closure is probably related to the fact that it used to be really a function pointer stored in
 | 
						|
             the class structure.
 | 
						|
            </para>
 | 
						|
          </footnote>
 | 
						|
      </para>
 | 
						|
    
 | 
						|
      <para>The following code shows the declaration of the <type>MamanFileSimple</type> class structure which contains
 | 
						|
        the <function>write</function> function pointer.
 | 
						|
<programlisting>
 | 
						|
struct _MamanFileSimpleClass {
 | 
						|
  GObjectClass parent;
 | 
						|
        
 | 
						|
  guint write_signal_id;
 | 
						|
 | 
						|
  /* signal default handlers */
 | 
						|
  void (*write) (MamanFileSimple *self, guint8 *buffer, guint size);
 | 
						|
};
 | 
						|
</programlisting>
 | 
						|
        The <function>write</function> function pointer is initialized in the class_init function of the object
 | 
						|
        to <function>default_write_signal_handler</function>:
 | 
						|
<programlisting>
 | 
						|
static void
 | 
						|
maman_file_simple_class_init (gpointer g_class,
 | 
						|
                               gpointer g_class_data)
 | 
						|
{
 | 
						|
  GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
 | 
						|
  MamanFileSimpleClass *klass = MAMAN_FILE_SIMPLE_CLASS (g_class);
 | 
						|
 | 
						|
  klass->write = default_write_signal_handler;
 | 
						|
</programlisting>
 | 
						|
        Finally, the signal is created with <function><link linkend="g-signal-new">g_signal_new</link></function> in the same class_init function:
 | 
						|
<programlisting>
 | 
						|
klass->write_signal_id = 
 | 
						|
 g_signal_new ("write",
 | 
						|
               G_TYPE_FROM_CLASS (g_class),
 | 
						|
               G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
 | 
						|
               G_STRUCT_OFFSET (MamanFileSimpleClass, write),
 | 
						|
               NULL /* accumulator */,
 | 
						|
               NULL /* accu_data */,
 | 
						|
               maman_file_complex_VOID__POINTER_UINT,
 | 
						|
               G_TYPE_NONE /* return_type */,
 | 
						|
               2     /* n_params */,
 | 
						|
               G_TYPE_POINTER,
 | 
						|
               G_TYPE_UINT);
 | 
						|
</programlisting>
 | 
						|
        Of note, here, is the 4th argument to the function: it is an integer calculated by the <function><link linkend="G-STRUCT-OFFSET">G_STRUCT_OFFSET</link></function>
 | 
						|
        macro which indicates the offset of the member <emphasis>write</emphasis> from the start of the 
 | 
						|
        <type>MamanFileSimpleClass</type> class structure.
 | 
						|
        <footnote>
 | 
						|
          <para>GSignal uses this offset to create a special wrapper closure 
 | 
						|
           which first retrieves the target function pointer before calling it.
 | 
						|
          </para>
 | 
						|
        </footnote>
 | 
						|
     </para>
 | 
						|
 | 
						|
     <para>
 | 
						|
       While the complete code for this type of default handler looks less cluttered as shown in 
 | 
						|
       <filename>sample/signal/maman-file-simple.{h|c}</filename>, it contains numerous subtleties.
 | 
						|
       The main subtle point which everyone must be aware of is that the signature of the default 
 | 
						|
       handler created that way does not have a user_data argument: 
 | 
						|
       <function>default_write_signal_handler</function> is different in 
 | 
						|
       <filename>sample/signal/maman-file-complex.c</filename> and in 
 | 
						|
       <filename>sample/signal/maman-file-simple.c</filename>.
 | 
						|
     </para>
 | 
						|
 | 
						|
     <para>If you have doubts about which method to use, I would advise you to use the second one which
 | 
						|
       involves <function><link linkend="g-signal-new">g_signal_new</link></function> rather than <function><link linkend="g-signal-newv">g_signal_newv</link></function>: 
 | 
						|
       it is better to write code which looks like the vast majority of other GTK+/GObject code than to
 | 
						|
       do it your own way. However, now, you know why.
 | 
						|
     </para>
 | 
						|
 | 
						|
   </sect2>
 | 
						|
 | 
						|
  </sect1>
 | 
						|
-->
 | 
						|
 | 
						|
<!--
 | 
						|
  yet another pointless section. if we are scared of possible abuses
 | 
						|
  from the users then we should not be mentioning it inside a tutorial
 | 
						|
  for beginners. but, obviously, there's nothing to be afraid of - it's
 | 
						|
  just that this section must be completely reworded.
 | 
						|
 | 
						|
  <sect1>
 | 
						|
    <title>How users can abuse signals (and why some think it is good)</title>
 | 
						|
 | 
						|
    <para>Now that you know how to create signals to which the users can connect easily and at any point in
 | 
						|
      the signal emission process thanks to <function><link linkend="g-signal-connect">g_signal_connect</link></function>, 
 | 
						|
      <function><link linkend="g-signal-connect-after">g_signal_connect_after</link></function> and G_SIGNAL_RUN_LAST, it is time to look into how your
 | 
						|
      users can and will screw you. This is also interesting to know how you too, can screw other people.
 | 
						|
      This will make you feel good and eleet.
 | 
						|
    </para>
 | 
						|
    
 | 
						|
    <para>
 | 
						|
      The users can:
 | 
						|
      <itemizedlist>
 | 
						|
         <listitem><para>stop the emission of the signal at anytime</para></listitem>
 | 
						|
         <listitem><para>override the default handler of the signal if it is stored as a function
 | 
						|
           pointer in the class structure (which is the preferred way to create a default signal handler,
 | 
						|
           as discussed in the previous section).</para></listitem>
 | 
						|
       </itemizedlist> 
 | 
						|
    </para>
 | 
						|
    
 | 
						|
    <para>
 | 
						|
      In both cases, the original programmer should be as careful as possible to write code which is
 | 
						|
      resistant to the fact that the default handler of the signal might not able to run. This is obviously
 | 
						|
      not the case in the example used in the previous sections since the write to the file depends on whether
 | 
						|
      or not the default handler runs (however, this might be your goal: to allow the user to prevent the file 
 | 
						|
      write if he wishes to).
 | 
						|
    </para>
 | 
						|
    
 | 
						|
    <para>
 | 
						|
      If all you want to do is to stop the signal emission from one of the callbacks you connected yourself,
 | 
						|
      you can call <function><link linkend="g-signal-stop-by-name">g_signal_stop_by_name</link></function>. Its use is very simple which is why I won't detail 
 | 
						|
      it further.
 | 
						|
    </para>
 | 
						|
    
 | 
						|
    <para>
 | 
						|
      If the signal's default handler is just a class function pointer, it is also possible to override 
 | 
						|
      it yourself from the class_init function of a type which derives from the parent. That way, when the signal
 | 
						|
      is emitted, the parent class will use the function provided by the child as a signal default handler.
 | 
						|
      Of course, it is also possible (and recommended) to chain up from the child to the parent's default signal 
 | 
						|
      handler to ensure the integrity of the parent object.
 | 
						|
    </para>
 | 
						|
    
 | 
						|
    <para>
 | 
						|
      Overriding a class method and chaining up was demonstrated in <xref linkend="howto-gobject-methods"/> 
 | 
						|
      which is why I won't bother to show exactly how to do it here again.
 | 
						|
    </para>
 | 
						|
 | 
						|
  </sect1>
 | 
						|
 | 
						|
-->
 | 
						|
 | 
						|
</chapter>
 | 
						|
 | 
						|
<!--
 | 
						|
  <sect2>
 | 
						|
    <title>Warning on signal creation and default closure</title>
 | 
						|
 | 
						|
    <para>
 | 
						|
      Most of the existing code I have seen up to now (in both GTK+, GNOME libraries and
 | 
						|
      many GTK+ and GNOME applications) using signals uses a small
 | 
						|
      variation of the default handler pattern I have shown in the previous section.
 | 
						|
    </para>
 | 
						|
 | 
						|
    <para>
 | 
						|
      Usually, the <function><link linkend="g-signal-new">g_signal_new</link></function> function is preferred over
 | 
						|
      <function><link linkend="g-signal-newv">g_signal_newv</link></function>. When <function><link linkend="g-signal-new">g_signal_new</link></function>
 | 
						|
      is used, the default closure is exported as a class function. For example,
 | 
						|
      <filename>gobject.h</filename> contains the declaration of <link linkend="GObjectClass"><type>GObjectClass</type></link>
 | 
						|
      whose notify class function is the default handler for the <emphasis>notify</emphasis>
 | 
						|
      signal:
 | 
						|
<programlisting>
 | 
						|
struct  _GObjectClass
 | 
						|
{
 | 
						|
  GTypeClass   g_type_class;
 | 
						|
 | 
						|
  /* class methods and other stuff. */
 | 
						|
 | 
						|
  /* signals */
 | 
						|
  void (*notify) (GObject     *object,
 | 
						|
                  GParamSpec  *pspec);
 | 
						|
};
 | 
						|
</programlisting>
 | 
						|
     </para>
 | 
						|
 | 
						|
     <para>
 | 
						|
       <filename>gobject.c</filename>'s <function><link linkend="g-object-do-class-init">g_object_do_class_init</link></function> function
 | 
						|
       registers the <emphasis>notify</emphasis> signal and initializes this class function
 | 
						|
       to NULL:
 | 
						|
<programlisting>
 | 
						|
static void
 | 
						|
g_object_do_class_init (GObjectClass *class)
 | 
						|
{
 | 
						|
 | 
						|
  /* Stuff */
 | 
						|
 | 
						|
  class->notify = NULL;
 | 
						|
 | 
						|
  gobject_signals[NOTIFY] =
 | 
						|
    g_signal_new ("notify",
 | 
						|
                  G_TYPE_FROM_CLASS (class),
 | 
						|
                  G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS,
 | 
						|
                  G_STRUCT_OFFSET (GObjectClass, notify),
 | 
						|
                  NULL, NULL,
 | 
						|
                  g_cclosure_marshal_VOID__PARAM,
 | 
						|
                  G_TYPE_NONE,
 | 
						|
                  1, G_TYPE_PARAM);
 | 
						|
}
 | 
						|
</programlisting>
 | 
						|
       <function><link linkend="g-signal-new">g_signal_new</link></function> creates a <link linkend="GClosure"><type>GClosure</type></link> which dereferences the
 | 
						|
       type's class structure to access the class function pointer and invoke it if it not NULL. The
 | 
						|
       class function is ignored it is set to NULL.
 | 
						|
     </para>
 | 
						|
 | 
						|
     <para>
 | 
						|
       To understand the reason for such a complex scheme to access the signal's default handler, 
 | 
						|
       you must remember the whole reason for the use of these signals. The goal here is to delegate
 | 
						|
       a part of the process to the user without requiring the user to subclass the object to override
 | 
						|
       one of the class functions. The alternative to subclassing, that is, the use of signals
 | 
						|
       to delegate processing to the user, is, however, a bit less optimal in terms of speed: rather
 | 
						|
       than just dereferencing a function pointer in a class structure, you must start the whole
 | 
						|
       process of signal emission which is a bit heavyweight.
 | 
						|
     </para>
 | 
						|
 | 
						|
     <para>
 | 
						|
       This is why some people decided to use class functions for some signal's default handlers:
 | 
						|
       rather than having users connect a handler to the signal and stop the signal emission
 | 
						|
       from within that handler, you just need to override the default class function which is
 | 
						|
       supposedly more efficient.
 | 
						|
     </para>
 | 
						|
 | 
						|
    </sect2>
 | 
						|
-->
 | 
						|
</part>
 |