--- /dev/null
+<?xml version='1.0' encoding="ISO-8859-1"?>
+
+ <chapter id="chapter-gobject">
+ <title>GObject: what brings everything together.</title>
+
+ <para>
+ The two previous chapters discussed the details of Glib's Dynamic Type System
+ and its signal control system. The GObject library also contains an implementation
+ for a base fundamental type named <type>GObject</type>.
+ </para>
+
+ <para>
+ <type>GObject</type> is a fundamental classed instantiable type. It implements:
+ <itemizedlist>
+ <listitem><para>Memory management with reference counting</para></listitem>
+ <listitem><para>Construction/Destruction of instances</para></listitem>
+ <listitem><para>Generic per-object properties with set/get function pairs</para></listitem>
+ <listitem><para>Easy use of signals</para></listitem>
+ </itemizedlist>
+ All the GTK objects and all of the objects in Gnome libraries which use the glib type
+ system inherit from <type>GObject</type> which is why it is important to understand
+ the details of how it works.
+ </para>
+
+ <sect1 id="gobject-instanciation">
+ <title>Object instanciation</title>
+
+ <para>
+ The <function>g_object_new</function> family of functions can be used to instantiate any
+ GType which inherits from the GObject base type. All these functions make sure the class
+ has been correctly initialized by glib's type system and then invoke at one
+ point or another the constructor class method which is used to:
+ <itemizedlist>
+ <listitem><para>
+ Allocate memory through <function>g_type_create_instance</function>,
+ </para></listitem>
+ <listitem><para>
+ Initialize the object' instance with the construction properties.
+ </para></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ Objects which inherit from GObject are allowed to override this constructor class method:
+ they should however chain to their parent constructor method before doing so:
+<programlisting>
+ GObject* (*constructor) (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties);
+</programlisting>
+ </para>
+
+ <para>
+ The example below shows how <type>MamanBar</type> overrides the parent's constructor:
+<programlisting>
+#define MAMAN_BAR_TYPE (maman_bar_get_type ())
+#define MAMAN_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_BAR_TYPE, MamanBar))
+#define MAMAN_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MAMAN_BAR_TYPE, MamanBarClass))
+#define MAMAN_IS_BAR(obj) (G_TYPE_CHECK_TYPE ((obj), MAMAN_BAR_TYPE))
+#define MAMAN_IS_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MAMAN_BAR_TYPE))
+#define MAMAN_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MAMAN_BAR_TYPE, MamanBarClass))
+
+typedef struct _MamanBar MamanBar;
+typedef struct _MamanBarClass MamanBarClass;
+
+struct _MamanBar {
+ GObject parent;
+ /* instance members */
+};
+
+struct _MamanBarClass {
+ GObjectClass parent;
+
+ /* class members */
+};
+
+/* used by MAMAN_BAR_TYPE */
+GType maman_bar_get_type (void);
+
+static GObject *
+maman_bar_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *obj;
+
+ {
+ /* Invoke parent constructor. */
+ MamanBarClass *klass;
+ GObjectClass *parent_class;
+ klass = MAMAN_BAR_CLASS (g_type_class_peek (MAMAN_BAR_TYPE));
+ parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
+ obj = parent_class->constructor (type,
+ n_construct_properties,
+ construct_properties);
+ }
+
+ /* do stuff. */
+
+ return obj;
+}
+
+static void
+maman_bar_instance_init (GTypeInstance *instance,
+ gpointer g_class)
+{
+ MamanBar *self = (MamanBar *)instance;
+ /* do stuff */
+}
+
+static void
+maman_bar_class_init (gpointer g_class,
+ gpointer g_class_data)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
+ MamanBarClass *klass = MAMAN_BAR_CLASS (g_class);
+
+ gobject_class->constructor = maman_bar_constructor;
+}
+
+GType maman_bar_get_type (void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (MamanBarClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ maman_bar_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (MamanBar),
+ 0, /* n_preallocs */
+ maman_bar_instance_init /* instance_init */
+ };
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "MamanBarType",
+ &info, 0);
+ }
+ return type;
+}
+</programlisting>
+ If the user instantiates an object <type>MamanBar</type> with:
+<programlisting>
+MamanBar *bar = g_object_new (MAMAN_BAR_TYPE, NULL);
+</programlisting>
+ If this is the first instantiation of such an object, the <function>maman_b_class_init</function>
+ function will be invoked after any <function>maman_b_base_class_init</function> function.
+ This will make sure the class structure of this new object is correctly initialized. Here,
+ <function>maman_bar_class_init</function> is expected to override the object's class methods
+ and setup the class' own methods. In the example above, the constructor method is the only
+ overridden method: it is set to <function>maman_bar_constructor</function>.
+ </para>
+
+ <para>
+ Once <function>g_object_new</function> has obtained a reference to an initialized
+ class structure, it invokes its constructor method to create an instance of the new
+ object. Since it has just been overridden by <function>maman_bar_class_init</function>
+ to <function>maman_bar_constructor</function>, the latter is called and, because it
+ was implemented correctly, it chains up to its parent's constructor. The problem here
+ is how we can find the parent constructor. An approach (used in GTK+ source code) would be
+ to save the original constructor in a static variable from <function>maman_bar_class_init</function>
+ and then to re-use it from <function>maman_bar_constructor</function>. This is clearly possible
+ and very simple but I was told it was not nice and the prefered way is to use the
+ <function>g_type_class_peek</function> and <function>g_type_class_peek_parent</function> functions.
+ </para>
+
+ <para>
+ Finally, at one point or another, <function>g_object_constructor</function> is invoked
+ by the last constructor in the chain. This function allocates the object's instance' buffer
+ through <function>g_type_create_instance</function>
+ which means that the instance_init function is invoked at this point if one
+ was registered. After instance_init returns, the object is fully initialized and should be
+ ready to answer any user-request. When <function>g_type_create_instance</function>
+ returns, <function>g_object_constructor</function> sets the construction properties
+ (ie: the properties which were given to <function>g_object_new</function>) and returns
+ to the user's constructor which is then allowed to do useful instance initialization...
+ </para>
+
+ <para>
+ The process described above might seem a bit complicated (it <emphasis>is</emphasis> actually
+ overly complicated in my opinion..) but it can be summarized easily by the table below which
+ lists the functions invoked by <function>g_object_new</function> and their order of
+ invocation.
+ </para>
+
+ <para>
+ The array below lists the functions invoked by <function>g_object_new</function> and
+ their order of invocation:
+
+ <table id="gobject-construction-table">
+ <title><function>g_object_new</function></title>
+ <tgroup cols="3">
+ <colspec colwidth="*" colnum="1" align="left"/>
+ <colspec colwidth="*" colnum="2" align="left"/>
+ <colspec colwidth="8*" colnum="3" align="left"/>
+
+ <thead>
+ <row>
+ <entry>Invocation time</entry>
+ <entry>Function Invoked</entry>
+ <entry>Function's parameters</entry>
+ <entry>Remark</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>First call to <function>g_object_new</function> for target type</entry>
+ <entry>target type's base_init function</entry>
+ <entry>On the inheritance tree of classes from fundamental type to target type.
+ base_init is invoked once for each class structure.</entry>
+ <entry>
+ I have no real idea on how this can be used. If you have a good real-life
+ example of how a class' base_init can be used, please, let me know.
+ </entry>
+ </row>
+ <row>
+ <entry>First call to <function>g_object_new</function> for target type</entry>
+ <entry>target type's class_init function</entry>
+ <entry>On target type's class structure</entry>
+ <entry>
+ Here, you should make sure to initialize or override class methods (that is,
+ assign to each class' method its function pointer) and create the signals and
+ the properties associated to your object.
+ </entry>
+ </row>
+ <row>
+ <entry>First call to <function>g_object_new</function> for target type</entry>
+ <entry>interface' base_init function</entry>
+ <entry>On interface' vtable</entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>First call to <function>g_object_new</function> for target type</entry>
+ <entry>interface' interface_init function</entry>
+ <entry>On interface' vtable</entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>Each call to <function>g_object_new</function> for target type</entry>
+ <entry>target type's class constructor method: GObjectClass->constructor</entry>
+ <entry>On object's instance</entry>
+ <entry>
+ If you need to complete the object initialization after all the construction properties
+ are set, override the constructor method and make sure to chain up to the object's
+ parent class before doing your own initialization.
+ In doubt, do not override the constructor method.
+ </entry>
+ </row>
+ <row>
+ <entry>Each call to <function>g_object_new</function> for target type</entry>
+ <entry>type's instance_init function</entry>
+ <entry>On the inheritance tree of classes from fundamental type to target type.
+ the instance_init provided for each type is invoked once for each instance
+ structure.</entry>
+ <entry>
+ Provide an instance_init function to initialize your object before its construction
+ properties are set. This is the preferred way to initialize a GObject instance.
+ This function is equivalent to C++ constructors.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </para>
+
+ <para>
+ Readers should feel concerned about one little twist in the order in which functions
+ are invoked: while, technically, the class' constructor method is called
+ <emphasis>before</emphasis> the GType's instance_init function (since
+ <function>g_type_create_instance</function> which calls instance_init is called by
+ <function>g_object_constructor</function> which is the top-level class
+ constructor method and to which users are expected to chain to), the user's code
+ which runs in a user-provided constructor will always run <emphasis>after</emphasis>
+ GType's instance_init function since the user-provided constructor
+ <emphasis>must</emphasis> (you've been warned) chain up <emphasis>before</emphasis>
+ doing anything useful.
+ </para>
+ </sect1>
+
+ <sect1 id="gobject-memory">
+ <title>Object memory management</title>
+
+ <para>
+ The memory-management API for GObjects is a bit complicated but the idea behind it
+ is pretty simple: the goal is to provide a flexible model based on reference counting
+ which can be integrated in applications which use or require different memory management
+ models (such as garbage collection, aso...)
+<programlisting>
+/*
+ Refcounting
+*/
+gpointer g_object_ref (gpointer object);
+void g_object_unref (gpointer object);
+
+/*
+ Weak References
+*/
+typedef void (*GWeakNotify) (gpointer data,
+ GObject *where_the_object_was);
+void g_object_weak_ref (GObject *object,
+ GWeakNotify notify,
+ gpointer data);
+void g_object_weak_unref (GObject *object,
+ GWeakNotify notify,
+ gpointer data);
+void g_object_add_weak_pointer (GObject *object,
+ gpointer *weak_pointer_location);
+void g_object_remove_weak_pointer (GObject *object,
+ gpointer *weak_pointer_location);
+/*
+ Cycle handling
+*/
+void g_object_run_dispose (GObject *object);
+</programlisting>
+ </para>
+
+ <sect2 id="gobject-memory-refcount">
+ <title>Reference count</title>
+
+ <para>
+ <function>g_object_ref</function>/<function>g_object_unref</function> respectively
+ increase and decrease the reference count. None of these function is thread-safe.
+ The reference count is, unsurprisingly, initialized to one by
+ <function>g_object_new</function>. When the reference count reaches zero, that is,
+ when <function>g_object_unref</function> is called by the last client holding
+ a reference to the object, the <emphasis>dispose</emphasis> and the
+ <emphasis>finalize</emphasis> class methods are invoked.
+ </para>
+ <para>
+ Finally, after <emphasis>finalize</emphasis> is invoked,
+ <function>g_type_free_instance</function> is called to free the object instance.
+ Depending on the memory allocation policy decided when the type was registered (through
+ one of the <function>g_type_register_*</function> functions), the object's instance
+ memory will be freed or returned to the object pool for this type.
+ Once the object has been freed, if it was the last instance of the type, the type's class
+ will be destroyed as described in <xref linkend="gtype-instantiable-classed"></xref> and
+ <xref linkend="gtype-non-instantiable-classed"></xref>.
+ </para>
+
+ <para>
+ The table below summarizes the destruction process of a GObject:
+ <table id="gobject-destruction-table">
+ <title><function>g_object_unref</function></title>
+ <tgroup cols="3">
+ <colspec colwidth="*" colnum="1" align="left"/>
+ <colspec colwidth="*" colnum="2" align="left"/>
+ <colspec colwidth="8*" colnum="3" align="left"/>
+
+ <thead>
+ <row>
+ <entry>Invocation time</entry>
+ <entry>Function Invoked</entry>
+ <entry>Function's parameters</entry>
+ <entry>Remark</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>Last call to <function>g_object_unref</function> for an instance
+ of target type</entry>
+ <entry>target type's dispose class function</entry>
+ <entry>GObject instance</entry>
+ <entry>
+ When dispose ends, the object should not hold any reference to any other
+ member object. The object is also expected to be able to answer client
+ method invocations (with possibly an error code but no memory violation)
+ until finalize is executed. dispose can be executed more than once.
+ dispose should chain up to its parent implementation just before returning
+ to the caller.
+ </entry>
+ </row>
+ <row>
+ <entry>Last call to <function>g_object_unref</function> for an instance
+ of target type
+ </entry>
+ <entry>target type's finalize class function</entry>
+ <entry>GObject instance</entry>
+ <entry>
+ Finalize is expected to complete the destruction process initiated by
+ dispose. It should complete the object's destruction. finalize will be
+ executed only once.
+ finalize should chain up to its parent implementation just before returning
+ to the caller.
+ The reason why the destruction process is split is two different phases is
+ explained in <xref linkend="gobject-memory-cycles"></xref>.
+ </entry>
+ </row>
+ <row>
+ <entry>Last call to <function>g_object_unref</function> for the last
+ instance of target type</entry>
+ <entry>interface' interface_finalize function</entry>
+ <entry>On interface' vtable</entry>
+ <entry>Never used in practice. Unlikely you will need it.</entry>
+ </row>
+ <row>
+ <entry>Last call to <function>g_object_unref</function>for the last
+ instance of target type</entry>
+ <entry>interface' base_finalize function</entry>
+ <entry>On interface' vtable</entry>
+ <entry>Never used in practice. Unlikely you will need it.</entry>
+ </row>
+ <row>
+ <entry>Last call to <function>g_object_unref</function> for the last
+ instance of target type</entry>
+ <entry>target type's class_finalize function</entry>
+ <entry>On target type's class structure</entry>
+ <entry>Never used in practice. Unlikely you will need it.</entry>
+ </row>
+ <row>
+ <entry>Last call to <function>g_object_unref</function> for the last
+ instance of target type</entry>
+ <entry>type's base_finalize function</entry>
+ <entry>On the inheritance tree of classes from fundamental type to target type.
+ base_init is invoked once for each class structure.</entry>
+ <entry>Never used in practice. Unlikely you will need it.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </para>
+
+ </sect2>
+
+ <sect2 id="gobject-memory-weakref">
+ <title>Weak References</title>
+
+ <para>
+ Weak References are used to monitor object finalization:
+ <function>g_object_weak_ref</function> adds a monitoring callback which does
+ not hold a reference to the object but which is invoked when the object runs
+ its dispose method. As such, each weak ref can be invoked more than once upon
+ object finalization (since dispose can run more than once during object
+ finalization).
+ </para>
+
+ <para>
+ <function>g_object_weak_unref</function> can be used to remove a monitoring
+ callback from the object.
+ </para>
+
+ <para>
+ Weak References are also used to implement <function>g_object_add_weak_pointer</function>
+ and <function>g_object_remove_weak_pointer</function>. These functions add a weak reference
+ to the object they are applied to which makes sure to nullify the pointer given by the user
+ when object is finalized.
+ </para>
+
+ </sect2>
+
+ <sect2 id="gobject-memory-cycles">
+ <title>Reference counts and cycles</title>
+
+ <para>
+ Note: the following section was inspired by James Henstridge. I guess this means that
+ all praise and all curses will be directly forwarded to him.
+ </para>
+
+ <para>
+ GObject's memory management model was designed to be easily integrated in existing code
+ using garbage collection. This is why the destruction process is split in two phases:
+ the first phase, executed in the dispose handler is supposed to release all references
+ to other member objects. The second phase, executed by the finalize handler is supposed
+ to complete the object's destruction process. Object methods should be able to run
+ without program error (that is, without segfault :) in-between the two phases.
+ </para>
+
+ <para>
+ This two-step destruction process is very useful to break reference counting cycles.
+ While the detection of the cycles is up to the external code, once the cycles have been
+ detected, the external code can invoke <function>g_object_dispose</function> which
+ will indeed break any existing cycles since it will run the dispose handler associated
+ to the object and thus release all references to other objects.
+ </para>
+
+ <para>
+ Attentive readers might now have understood one of the rules about the dispose handler
+ we stated a bit sooner: the dispose handler can be invoked multiple times. Let's say we
+ have a reference count cycle: object A references B which itself references object A.
+ Let's say we have detected the cycle and we want to destroy the two objects. One way to
+ do this would be to invoke <function>g_object_dispose</function> on one of the
+ objects.
+ </para>
+
+ <para>
+ If object A releases all its references to all objects, this means it releases its
+ reference to object B. If object B was not owned by anyone else, this is its last
+ reference count which means this last unref runs B's dispose handler which, in turn,
+ releases B's reference on object A. If this is A's last reference count, this last
+ unref runs A's dispose handler which is running for the second time before
+ A's finalize handler is invoked !
+ </para>
+
+ <para>
+ The above example, which might seem a bit contrived can really happen if your
+ GObject's are being by language bindings. I would thus suggest the rules stated above
+ for object destruction are closely followed. Otherwise, <emphasis>Bad Bad Things</emphasis>
+ will happen.
+ </para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="gobject-properties">
+ <title>Object properties</title>
+
+ <para>
+ One of GObject's nice features is its generic get/set mechanism. When an object
+ is instanciated, the object's class_init handler should be used to register
+ the object's properties with <function>g_object_class_install_property</function>
+ (implemented in <filename>gobject.c</filename>).
+ </para>
+
+ <para>
+ The best way to understand how object properties work is by looking at a real example
+ on how it is used:
+<programlisting>
+/************************************************/
+/* Implementation */
+/************************************************/
+
+enum {
+ MAMAN_BAR_CONSTRUCT_NAME = 1,
+ MAMAN_BAR_PAPA_NUMBER = 2,
+};
+
+static void
+maman_bar_instance_init (GTypeInstance *instance,
+ gpointer g_class)
+{
+ MamanBar *self = (MamanBar *)instance;
+}
+
+
+static void
+maman_bar_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MamanBar *self = (MamanBar *) object;
+
+ switch (property_id) {
+ case MAMAN_BAR_CONSTRUCT_NAME: {
+ g_free (self->private->name);
+ self->private->name = g_value_dup_string (value);
+ g_print ("maman: %s\n",self->private->name);
+ }
+ break;
+ case MAMAN_BAR_PAPA_NUMBER: {
+ self->private->papa_number = g_value_get_uchar (value);
+ g_print ("papa: %u\n",self->private->papa_number);
+ }
+ break;
+ default:
+ /* We don't have any other property... */
+ g_assert (FALSE);
+ break;
+ }
+}
+
+static void
+maman_bar_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MamanBar *self = (MamanBar *) object;
+
+ switch (property_id) {
+ case MAMAN_BAR_CONSTRUCT_NAME: {
+ g_value_set_string (value, self->private->name);
+ }
+ break;
+ case MAMAN_BAR_PAPA_NUMBER: {
+ g_value_set_uchar (value, self->private->papa_number);
+ }
+ break;
+ default:
+ /* We don't have any other property... */
+ g_assert (FALSE);
+ break;
+ }
+}
+
+static void
+maman_bar_class_init (gpointer g_class,
+ gpointer g_class_data)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
+ MamanBarClass *klass = MAMAN_BAR_CLASS (g_class);
+ GParamSpec *pspec;
+
+ gobject_class->set_property = maman_bar_set_property;
+ gobject_class->get_property = maman_bar_get_property;
+
+ pspec = g_param_spec_string ("maman-name",
+ "Maman construct prop",
+ "Set maman's name",
+ "no-name-set" /* default value */,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+ g_object_class_install_property (gobject_class,
+ MAMAN_BAR_CONSTRUCT_NAME,
+ pspec);
+
+ pspec = g_param_spec_uchar ("papa-number",
+ "Number of current Papa",
+ "Set/Get papa's number",
+ 0 /* minimum value */,
+ 10 /* maximum value */,
+ 2 /* default value */,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (gobject_class,
+ MAMAN_BAR_PAPA_NUMBER,
+ pspec);
+}
+
+/************************************************/
+/* Use */
+/************************************************/
+
+GObject *bar;
+GValue val = {0,};
+bar = g_object_new (MAMAN_SUBBAR_TYPE, NULL);
+g_value_init (&val, G_TYPE_CHAR);
+g_value_set_char (&val, 11);
+g_object_set_property (G_OBJECT (bar), "papa-number", &val);
+</programlisting>
+ The client code just above looks simple but a lot of things happen under the hood:
+ </para>
+
+ <para>
+ <function>g_object_set_property</function> first ensures a property
+ with this name was registered in bar's class_init handler. If so, it calls
+ <function>object_set_property</function> which first walks the class hierarchy,
+ from bottom, most derived type, to top, fundamental type to find the class
+ which registered that property. It then tries to convert the user-provided GValue
+ into a GValue whose type if that of the associated property.
+ </para>
+
+ <para>
+ If the user provides a signed char GValue, as is shown
+ here, and if the object's property was registered as an unsigned int,
+ <function>g_value_transform</function> will try to transform the input signed char into
+ an unsigned int. Of course, the success of the transformation depends on the availability
+ of the required transform function. In practice, there will almost always be a transformation
+ <footnote>
+ <para>Its behaviour might not be what you expect but it is up to you to actually avoid
+ relying on these transformations.
+ </para>
+ </footnote>
+ which matches and conversion will be caried out if needed.
+ </para>
+
+ <para>
+ After transformation, the <type>GValue</type> is validated by
+ <function>g_param_value_validate</function> which makes sure the user's
+ data stored in the <type>GValue</type> matches the characteristics specified by
+ the property's <type>GParamSpec</type>. Here, the <type>GParamSpec</type> we
+ provided in class_init has a validation function which makes sure that the GValue
+ contains a value which respects the minimum and maximum bounds of the
+ <type>GParamSpec</type>. In the example above, the client's GValue does not
+ respect these constraints (it is set to 11, while the maximum is 10). As such, the
+ <function>g_object_set_property</function> function will return with an error.
+ </para>
+
+ <para>
+ If the user's GValue had been set to a valid value, <function>object_set_property</function>
+ would have proceeded with calling the object's set_property class method. Here, since our
+ implementation of Foo did override this method, the code path would jump to
+ <function>foo_set_property</function> after having retrieved from the
+ <type>GParamSpec</type> the <emphasis>param_id</emphasis>
+ <footnote>
+ <para>
+ It should be noted that the param_id used here need only to uniquely identify each
+ <type>GParamSpec</type> within the <type>FooClass</type> such that the switch
+ used in the set and get methods actually works. Of course, this locally-unique
+ integer is purely an optimization: it would have been possible to use a set of
+ <emphasis>if (strcmp (a, b) == 0) {} else if (strcmp (a, b) == 0) {}</emphasis> statements.
+ </para>
+ </footnote>
+ which had been stored by
+ <function>g_object_class_install_property</function>.
+ </para>
+
+ <para>
+ Once the property has been set by the object's set_property class method, the code path
+ returns to <function>g_object_set_property</function> which calls
+ <function>g_object_notify_queue_thaw</function>. This function makes sure that
+ the "notify" signal is emitted on the object's instance with the changed property as
+ parameter unless notifications were frozen by <function>g_object_freeze_notify</function>.
+ </para>
+
+ <para>
+ <function>g_object_thaw_notify</function> can be used to re-enable notification of
+ property modifications through the "notify" signal. It is important to remember that
+ even if properties are changed while property change notification is frozen, the "notify"
+ signal will be emitted once for each of these changed properties as soon as the property
+ change notification is thawn: no property change is lost for the "notify" signal. Signal
+ can only be delayed by the notification freezing mechanism.
+ </para>
+
+ <para>
+ It is interesting to note that the <function>g_object_set</function> and
+ <function>g_object_set_valist</function> (vararg version) functions can be used to set
+ multiple properties at once. The client code shown above can then be re-written as:
+<programlisting>
+MamanBar *foo;
+foo = /* */;
+g_object_set (G_OBJECT (foo),
+ "papa-number", 2,
+ "maman-name", "test",
+ NULL);
+</programlisting>
+ The code above will trigger one notify signal emission for each property modified.
+ </para>
+
+ <para>
+ Of course, the _get versions are also available: <function>g_object_get</function>
+ and <function>g_object_get_valist</function> (vararg version) can be used to get numerous
+ properties at once.
+ </para>
+
+ <para>
+ Really attentive readers now understand how <function>g_object_new</function>,
+ <function>g_object_newv</function> and <function>g_object_new_valist</function>
+ work: they parse the user-provided variable number of parameters and invoke
+ <function>g_object_set</function> on each pair of parameters only after the object has been successfully constructed.
+ Of course, the "notify" signal will be emitted for each property set.
+ </para>
+
+ </sect1>
+
+ </chapter>
+
+
+
+
--- /dev/null
+<?xml version='1.0' encoding="ISO-8859-1"?>
+ <chapter id="chapter-signal">
+ <title>Signals</title>
+
+ <sect1 id="closure">
+ <title>Closures</title>
+
+ <para>
+ Closures are central to the concept of asynchronous signal delivery
+ which is widely used throughout GTK+ and Gnome applications. A Closure is an
+ abstraction, a generic representation of a callback. It is a small structure
+ which contains three objects:
+ <itemizedlist>
+ <listitem><para>a function pointer (the callback itself) whose prototype looks like:
+<programlisting>
+return_type function_callback (... , gpointer user_data);
+</programlisting>
+ </para></listitem>
+ <listitem><para>
+ the user_data pointer which is passed to the callback upon invocation of the closure
+ </para></listitem>
+ <listitem><para>
+ a function pointer which represents the destructor of the closure: whenever the
+ closure's refcount reaches zero, this function will be called before the closure
+ structure is freed.
+ </para></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ The <type>GClosure</type> structure represents the common functionality of all
+ closure implementations: there exist a different Closure implementation for
+ each separate runtime which wants to use the GObject type system.
+ <footnote><para>
+ In Practice, Closures sit at the boundary of language runtimes: if you are
+ writing python code and one of your Python callback receives a signal from
+ one of GTK+ widgets, the C code in GTK+ needs to execute your Python
+ code. The Closure invoked by the GTK+ object invokes the Python callback:
+ it behaves as a normal C object for GTK+ and as a normal Python object for
+ python code.
+ </para></footnote>
+ The GObject library provides a simple <type>GCClosure</type> type which
+ is a specific implementation of closures to be used with C/C++ callbacks.
+ </para>
+ <para>
+ A <type>GClosure</type> provides simple services:
+ <itemizedlist>
+ <listitem><para>
+ Invocation (<function>g_closure_invoke</function>): this is what closures
+ were created for: they hide the details of callback invocation from the
+ callback invocator.
+ </para></listitem>
+ <listitem><para>
+ Notification: the closure notifies listeners of certain events such as
+ closure invocation, closure invalidation and closure finalization. Listeners
+ can be registered with <function>g_closure_add_finalize_notifier</function>
+ (finalization notification), <function>g_closure_add_invalidate_notifier</function>
+ (invalidation notification) and
+ <function>g_closure_add_marshal_guards</function> (invocation notification).
+ There exist symmetric de-registration functions for finalization and invalidation
+ events (<function>g_closure_remove_finalize_notifier</function> and
+ <function>g_closure_remove_invalidate_notifier</function>) but not for the invocation
+ process.
+ <footnote><para>
+ Closures are refcounted and notify listeners of their destruction in a two-stage
+ process: the invalidation notifiers are invoked before the finalization notifiers.
+ </para></footnote>
+ </para></listitem>
+ </itemizedlist>
+ </para>
+
+ <sect2>
+ <title>C Closures</title>
+
+ <para>
+ If you are using C or C++
+ to connect a callback to a given event, you will either use the simple <type>GCClosure</type>s
+ which have a pretty minimal API or the even simpler <function>g_signal_connect</function>
+ functions (which will be presented a bit later :).
+ <programlisting>
+GClosure* g_cclosure_new (GCallback callback_func,
+ gpointer user_data,
+ GClosureNotify destroy_data);
+GClosure* g_cclosure_new_swap (GCallback callback_func,
+ gpointer user_data,
+ GClosureNotify destroy_data);
+GClosure* g_signal_type_cclosure_new (GType itype,
+ guint struct_offset);
+ </programlisting>
+ </para>
+
+ <para>
+ <function>g_cclosure_new</function> will create a new closure which can invoke the
+ user-provided callback_func with the user-provided user_data as last parameter. When the closure
+ is finalized (second stage of the destruction process), it will invoke the destroy_data function
+ if the user has supplied one.
+ </para>
+
+ <para>
+ <function>g_cclosure_new_swap</function> will create a new closure which can invoke the
+ user-provided callback_func with the user-provided user_data as first parameter (instead of being the
+ last parameter as with <function>g_cclosure_new</function>). When the closure
+ is finalized (second stage of the destruction process), it will invoke the destroy_data
+ function if the user has supplied one.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>non-C closures (for the fearless).</title>
+
+ <para>
+ As was explained above, Closures hide the details of callback invocation. In C,
+ callback invocation is just like function invocation: it is a matter of creating
+ the correct stack frame for the called function and executing a <emphasis>call</emphasis>
+ assembly instruction.
+ </para>
+
+ <para>
+ C closure marshallers transform the array of GValues which represent
+ the parameters to the target function into a C-style function parameter list, invoke
+ the user-supplied C function with this new parameter list, get the return value of the
+ function, transform it into a GValue and return this GValue to the marshaller caller.
+ </para>
+
+ <para>
+ The following code implements a simple marshaller in C for a C function which takes an
+ integer as first parameter and returns void.
+ <programlisting>
+g_cclosure_marshal_VOID__INT (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__INT) (gpointer data1,
+ gint arg_1,
+ gpointer data2);
+ register GMarshalFunc_VOID__INT callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 2);
+
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+
+ callback = (GMarshalFunc_VOID__INT) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_int (param_values + 1),
+ data2);
+}
+ </programlisting>
+ </para>
+
+ <para>
+ Of course, there exist other kinds of marshallers. For example, James Henstridge
+ wrote a generic Python marshaller which is used by all python Closures (a python closure
+ is used to have python-based callback be invoked by the closure invocation process).
+ This python marshaller transforms the input GValue list representing the function
+ parameters into a Python tupple which is the equivalent structure in python (you can
+ look in <function>pyg_closure_marshal</function> in <filename>pygtype.c</filename>
+ in the <emphasis>pygtk</emphasis> module in Gnome cvs server).
+ </para>
+
+ </sect2>
+ </sect1>
+
+ <sect1 id="signal">
+ <title>Signals</title>
+
+ <para>
+ GObject's signals have nothing to do with standard UNIX signals: they connect
+ arbitrary application-specific events with any number of listeners.
+ For example, in GTK, every user event (keystroke or mouse move) is received
+ from the X server and generates a GTK+ event under the form of a signal emission
+ on a given object instance.
+ </para>
+
+ <para>
+ Each signal is registered in the type system together with the type on which
+ it can be emitted: users of the type are said to <emphasis>connect</emphasis>
+ to the signal on a given type instance when they register a closure to be
+ invoked upon the signal emission. Users can also emit the signal by themselves
+ or stop the emission of the signal from within one of the closures connected
+ to the signal.
+ </para>
+
+ <para>
+ When a signal is emitted on a given type instance, all the closures
+ connected to this signal on this type instance will be invoked. All the closures
+ connected to such a signal represent callbacks whose signature looks like:
+<programlisting>
+return_type function_callback (gpointer instance, ... , gpointer user_data);
+</programlisting>
+ </para>
+
+ <sect2 id="signal-registration">
+ <title>Signal registration</title>
+
+ <para>
+ To register a new signal on an existing type, we can use any of <function>g_signal_newv</function>,
+ <function>g_signal_new_valist</function> or <function>g_signal_new</function> functions:
+<programlisting>
+guint g_signal_newv (const gchar *signal_name,
+ GType itype,
+ GSignalFlags signal_flags,
+ GClosure *class_closure,
+ GSignalAccumulator accumulator,
+ gpointer accu_data,
+ GSignalCMarshaller c_marshaller,
+ GType return_type,
+ guint n_params,
+ GType *param_types);
+</programlisting>
+ The number of parameters to these functions is a bit intimidating but they are relatively
+ simple:
+ <itemizedlist>
+ <listitem><para>
+ signal_name: is a string which can be used to uniquely identify a given signal.
+ </para></listitem>
+ <listitem><para>
+ itype: is the instance type on which this signal can be emitted.
+ </para></listitem>
+ <listitem><para>
+ signal_flags: partly defines the order in which closures which were connected to the
+ signal are invoked.
+ </para></listitem>
+ <listitem><para>
+ class_closure: this is the default closure for the signal: if it is not NULL upon
+ the signal emission, it will be invoked upon this emission of the signal. The
+ moment where this closure is invoked compared to other closures connected to that
+ signal depends partly on the signal_flags.
+ </para></listitem>
+ <listitem><para>
+ accumulator: this is a function pointer which is invoked after each closure
+ has been invoked. If it returns FALSE, signal emission is stopped. If it returns
+ TRUE, signal emission proceeds normally. It is also used to compute the return
+ value of the signal based on the return value of all the invoked closures.
+ </para></listitem>
+ <listitem><para>
+ accumulator_data: this pointer will be passed down to each invocation of the
+ accumulator during emission.
+ </para></listitem>
+ <listitem><para>
+ c_marshaller: this is the default C marshaller for any closure which is connected to
+ this signal.
+ </para></listitem>
+ <listitem><para>
+ return_type: this is the type of the return value of the signal.
+ </para></listitem>
+ <listitem><para>
+ n_params: this is the number of parameters this signal takes.
+ </para></listitem>
+ <listitem><para>
+ param_types: this is an array of GTypes which indicate the type of each parameter
+ of the signal. The length of this array is indicated by n_params.
+ </para></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ As you can see from the above definition, a signal is basically a description
+ of the closures which can be connected to this signal and a description of the
+ order in which the closures connected to this signal will be invoked.
+ </para>
+
+ </sect2>
+
+ <sect2 id="signal-connection">
+ <title>Signal connection</title>
+
+ <para>
+ If you want to connect to a signal with a closure, you have three possibilities:
+ <itemizedlist>
+ <listitem><para>
+ You can register a class closure at signal registration: this is a
+ system-wide operation. i.e.: the class_closure will be invoked during each emission
+ of a given signal on all the instances of the type which supports that signal.
+ </para></listitem>
+ <listitem><para>
+ You can use <function>g_signal_override_class_closure</function> which
+ overrides the class_closure of a given type. It is possible to call this function
+ only on a derived type of the type on which the signal was registered.
+ This function is of use only to language bindings.
+ </para></listitem>
+ <listitem><para>
+ You can register a closure with the <function>g_signal_connect</function>
+ family of functions. This is an instance-specific operation: the closure
+ will be invoked only during emission of a given signal on a given instance.
+ </para></listitem>
+ </itemizedlist>
+ It is also possible to connect a different kind of callback on a given signal:
+ emission hooks are invoked whenever a given signal is emitted whatever the instance on
+ which it is emitted. Emission hooks are used for example to get all mouse_clicked
+ emissions in an application to be able to emit the small mouse click sound.
+ Emission hooks are connected with <function>g_signal_add_emission_hook</function>
+ and removed with <function>g_signal_remove_emission_hook</function>.
+ </para>
+
+ <para>
+ </para>
+
+ </sect2>
+
+ <sect2 id="signal-emission">
+ <title>Signal emission</title>
+
+ <para>
+ Signal emission is done through the use of the <function>g_signal_emit</function> family
+ of functions.
+<programlisting>
+void g_signal_emitv (const GValue *instance_and_params,
+ guint signal_id,
+ GQuark detail,
+ GValue *return_value);
+</programlisting>
+ <itemizedlist>
+ <listitem><para>
+ The instance_and_params array of GValues contains the list of input
+ parameters to the signal. The first element of the array is the
+ instance pointer on which to invoke the signal. The following elements of
+ the array contain the list of parameters to the signal.
+ </para></listitem>
+ <listitem><para>
+ signal_id identifies the signal to invoke.
+ </para></listitem>
+ <listitem><para>
+ detail identifies the specific detail of the signal to invoke. A detail is a kind of
+ magic token/argument which is passed around during signal emission and which is used
+ by closures connected to the signal to filter out unwanted signal emissions. In most
+ cases, you can safely set this value to zero. See <xref linkend="signal-detail"/> for
+ more details about this parameter.
+ </para></listitem>
+ <listitem><para>
+ return_value holds the return value of the last closure invoked during emission if
+ no accumulator was specified. If an accumulator was specified during signal creation,
+ this accumulator is used to calculate the return_value as a function of the return
+ values of all the closures invoked during emission.
+ <footnote><para>
+ James (again!!) gives a few non-trivial examples of accumulators:
+ <quote>
+ For instance, you may have an accumulator that ignores NULL returns from
+ closures, and only accumulates the non-NULL ones. Another accumulator may try
+ to return the list of values returned by the closures.
+ </quote>
+ </para></footnote>
+ If no closure is invoked during
+ emission, the return_value is nonetheless initialized to zero/null.
+ </para></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ Internally, the GValue array is passed to the emission function proper,
+ <function>signal_emit_unlocked_R</function> (implemented in <filename>gsignal.c</filename>).
+ Signal emission can be decomposed in 5 steps:
+ <itemizedlist>
+ <listitem><para>
+ <emphasis>RUN_FIRST</emphasis>: if the G_SIGNAL_RUN_FIRST flag was used
+ during signal registration and if there exist a class_closure for this signal,
+ the class_closure is invoked. Jump to <emphasis>EMISSION_HOOK</emphasis> state.
+ </para></listitem>
+ <listitem><para>
+ <emphasis>EMISSION_HOOK</emphasis>: if any emission hook was added to
+ the signal, they are invoked from first to last added. Accumulate return values
+ and jump to <emphasis>HANDLER_RUN_FIRST</emphasis> state.
+ </para></listitem>
+ <listitem><para>
+ <emphasis>HANDLER_RUN_FIRST</emphasis>: if any closure were connected
+ with the <function>g_signal_connect</function> family of
+ functions, and if they are not blocked (with the <function>g_signal_handler_block</function>
+ family of functions) they are run here, from first to last connected.
+ Jump to <emphasis>RUN_LAST</emphasis> state.
+ </para></listitem>
+ <listitem><para>
+ <emphasis>RUN_LAST</emphasis>: if the G_SIGNAL_RUN_LAST
+ flag was set during registration and if a class_closure
+ was set, it is invoked here. Jump to
+ <emphasis>HANDLER_RUN_LAST</emphasis> state.
+ </para></listitem>
+ <listitem><para>
+ <emphasis>HANDLER_RUN_LAST</emphasis>: if any closure were connected
+ with the <function>g_signal_connect_after</function> family of
+ functions, if they were not invoked during HANDLER_RUN_FIRST and if they
+ are not blocked, they are run here, from first to last connected.
+ Jump to <emphasis>RUN_CLEANUP</emphasis> state.
+ </para></listitem>
+ <listitem><para>
+ <emphasis>RUN_CLEANUP</emphasis>: if the G_SIGNAL_RUN_CLEANUP flag
+ was set during registration and if a class_closure was set,
+ it is invoked here. Signal emission is completed here.
+ </para></listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ If, at any point during emission (except in RUN_CLEANUP state), one of the
+ closures or emission hook stops the signal emission with
+ <function>g_signal_stop</function>, emission jumps to CLEANUP state.
+ </para>
+
+ <para>
+ If, at any point during emission, one of the closures or emission hook
+ emits the same signal on the same instance, emission is restarted from
+ the RUN_FIRST state.
+ </para>
+
+ <para>
+ The accumulator function is invoked in all states, after invocation
+ of each closure (except in EMISSION_HOOK and CLEANUP). It accumulates
+ the closure return value into the signal return value and returns TRUE or
+ FALSE. If, at any point, it does not return TRUE, emission jumps to CLEANUP state.
+ </para>
+
+ <para>
+ If no accumulator function was provided, the value returned by the last handler
+ run will be returned by <function>g_signal_emit</function>.
+ </para>
+
+ </sect2>
+
+
+ <sect2 id="signal-detail">
+ <title>The <emphasis>detail</emphasis> argument</title>
+
+ <para>All the functions related to signal emission or signal connection have a parameter
+ named the <emphasis>detail</emphasis>. Sometimes, this parameter is hidden by the API
+ but it is always there, under one form or another.
+ </para>
+
+ <para>
+ Of the three main connection functions,
+ only one has an explicit detail parameter as a <type>GQuark</type>
+ <footnote>
+ <para>A GQuark is an integer which uniquely represents a string. It is possible to transform
+ back and forth between the integer and string representations with the functions
+ <function>g_quark_from_string</function> and <function>g_quark_to_string</function>.
+ </para>
+ </footnote>:
+<programlisting>
+gulong g_signal_connect_closure_by_id (gpointer instance,
+ guint signal_id,
+ GQuark detail,
+ GClosure *closure,
+ gboolean after);
+</programlisting>
+ The two other functions hide the detail parameter in the signal name identification:
+<programlisting>
+gulong g_signal_connect_closure (gpointer instance,
+ const gchar *detailed_signal,
+ GClosure *closure,
+ gboolean after);
+gulong g_signal_connect_data (gpointer instance,
+ const gchar *detailed_signal,
+ GCallback c_handler,
+ gpointer data,
+ GClosureNotify destroy_data,
+ GConnectFlags connect_flags);
+</programlisting>
+ Their detailed_signal parameter is a string which identifies the name of the signal
+ to connect to. However, the format of this string is structured to look like
+ <emphasis>signal_name::detail_name</emphasis>. Connecting to the signal
+ named <emphasis>notify::cursor_position</emphasis> will actually connect to the signal
+ named <emphasis>notify</emphasis> with the <emphasis>cursor_position</emphasis> name.
+ Internally, the detail string is transformed to a GQuark if it is present.
+ </para>
+
+ <para>
+ Of the four main signal emission functions, three have an explicit detail parameter as a
+ <type>GQuark</type> again:
+<programlisting>
+void g_signal_emitv (const GValue *instance_and_params,
+ guint signal_id,
+ GQuark detail,
+ GValue *return_value);
+void g_signal_emit_valist (gpointer instance,
+ guint signal_id,
+ GQuark detail,
+ va_list var_args);
+void g_signal_emit (gpointer instance,
+ guint signal_id,
+ GQuark detail,
+ ...);
+</programlisting>
+ The fourth function hides it in its signal name parameter:
+<programlisting>
+void g_signal_emit_by_name (gpointer instance,
+ const gchar *detailed_signal,
+ ...);
+</programlisting>
+ The format of the detailed_signal parameter is exactly the same as the format used by
+ the <function>g_signal_connect</function> functions: <emphasis>signal_name::detail_name</emphasis>.
+ </para>
+
+ <para>
+ If a detail is provided by the user to the emission function, it is used during emission to match
+ against the closures which also provide a detail. The closures which provided a detail will not
+ be invoked (even though they are connected to a signal which is being emitted) if their detail
+ does not match the detail provided by the user.
+ </para>
+
+ <para>This completely optional filtering mechanism is mainly used as an optimization for signals
+ which are often emitted for many different reasons: the clients can filter out which events they are
+ interested into before the closure's marshalling code runs. For example, this is used extensively
+ by the <emphasis>notify</emphasis> signal of GObject: whenever a property is modified on a GObject,
+ instead of just emitting the <emphasis>notify</emphasis> signal, GObject associates as a detail to this
+ signal emission the name of the property modified. This allows clients who wish to be notified of changes
+ to only one property to filter most events before receiving them.
+ </para>
+
+ <para>As a simple rule, users can and should set the detail parameter to zero: this will disable completely
+ this optional filtering.
+ </para>
+
+ </sect2>
+
+ </sect1>
+ </chapter>
--- /dev/null
+<?xml version='1.0' encoding="ISO-8859-1"?>
+ <chapter>
+ <title>The Glib Dynamic Type System</title>
+
+ <para>
+ A type, as manipulated by the Glib type system, is much more generic than what
+ is usually understood as an Object type. It is best explained by looking at the
+ structure and the functions used to register new types in the type system.
+ <programlisting>
+typedef struct _GTypeInfo GTypeInfo;
+struct _GTypeInfo
+{
+ /* interface types, classed types, instantiated types */
+ guint16 class_size;
+
+ GBaseInitFunc base_init;
+ GBaseFinalizeFunc base_finalize;
+
+ /* classed types, instantiated types */
+ GClassInitFunc class_init;
+ GClassFinalizeFunc class_finalize;
+ gconstpointer class_data;
+
+ /* instantiated types */
+ guint16 instance_size;
+ guint16 n_preallocs;
+ GInstanceInitFunc instance_init;
+
+ /* value handling */
+ const GTypeValueTable *value_table;
+};
+GType g_type_register_static (GType parent_type,
+ const gchar *type_name,
+ const GTypeInfo *info,
+ GTypeFlags flags);
+GType g_type_register_fundamental (GType type_id,
+ const gchar *type_name,
+ const GTypeInfo *info,
+ const GTypeFundamentalInfo *finfo,
+ GTypeFlags flags);
+ </programlisting>
+ </para>
+
+ <para>
+ <function>g_type_register_static</function> and
+ <function>g_type_register_fundamental</function>
+ are the C functions, defined in
+ <filename>gtype.h</filename> and implemented in <filename>gtype.c</filename>
+ which you should use to register a new type in the program's type system.
+ It is not likely you will ever need to use
+ <function>g_type_register_fundamental</function> (you have to be Tim Janik
+ to do that) but in case you want to, the last chapter explains how to create
+ new fundamental types.
+ <footnote>
+ <para>
+ Please, note that there exist another registration function: the
+ <function>g_type_register_dynamic</function>. We will not discuss this
+ function here since its use is very similar to the <function>_static</function>
+ version.
+ </para>
+ </footnote>
+ </para>
+
+ <para>
+ Fundamental types are top-level types which do not derive from any other type
+ while other non-fundamental types derive from other types.
+ Upon initialization by <function>g_type_init</function>, the type system not
+ only initializes its internal data structures but it also registers a number of core
+ types: some of these are fundamental types. Others are types derived from these
+ fundamental types.
+ </para>
+
+ <para>
+ Fundamental and non-Fundamental types are defined by:
+ <itemizedlist>
+ <listitem><para>
+ class size: the class_size field in <type>GTypeInfo</type>.
+ </para></listitem>
+ <listitem><para>
+ class initialization functions (C++ constructor): the base_init and
+ class_init fields in <type>GTypeInfo</type>.
+ </para></listitem>
+ <listitem><para>
+ class destruction functions (C++ destructor): the base_finalize and
+ class_finalize fields in <type>GTypeInfo</type>.
+ </para></listitem>
+ <listitem><para>
+ instance size (C++ parameter to new): the instance_size field in
+ <type>GTypeInfo</type>.
+ </para></listitem>
+ <listitem><para>
+ instanciation policy (C++ type of new operator): the n_preallocs
+ field in <type>GTypeInfo</type>.
+ </para></listitem>
+ <listitem><para>
+ copy functions (C++ copy operators): the value_table field in
+ <type>GTypeInfo</type>.
+ </para></listitem>
+ <listitem><para>
+ XXX: <type>GTypeFlags</type>.
+ </para></listitem>
+ </itemizedlist>
+ Fundamental types are also defined by a set of <type>GTypeFundamentalFlags</type>
+ which are stored in a <type>GTypeFundamentalInfo</type>.
+ Non-Fundamental types are furthermore defined by the type of their parent which is
+ passed as the parent_type parameter to <function>g_type_register_static</function>
+ and <function>g_type_register_dynamic</function>.
+ </para>
+
+ <sect1 id="gtype-copy">
+ <title>Copy functions</title>
+
+ <para>
+ The major common point between <emphasis>all</emphasis> glib types (fundamental and
+ non-fundamental, classed and non-classed, instantiable and non-instantiable) is that
+ they can all be manipulated through a single API to copy/assign them.
+ </para>
+
+ <para>
+ The <type>GValue</type> structure is used as an abstract container for all of these
+ types. Its simplistic API (defined in <filename>gobject/gvalue.h</filename>) can be
+ used to invoke the value_table functions registered
+ during type registration: for example <function>g_value_copy</function> copies the
+ content of a <type>GValue</type> to another <type>GValue</type>. This is similar
+ to a C++ assignment which invokes the C++ copy operator to modify the default
+ bit-by-bit copy semantics of C++/C structures/classes.
+ </para>
+
+ <para>
+ The following code shows shows you can copy around a 64 bit integer, as well as a <type>GObject</type>
+ instance pointer (sample code for this is located in the source tarball for this document in
+ <filename>sample/gtype/test.c</filename>):
+<programlisting>
+static void test_int (void)
+{
+ GValue a_value = {0, };
+ GValue b_value = {0, };
+ guint64 a, b;
+
+ a = 0xdeadbeaf;
+
+ g_value_init (&a_value, G_TYPE_UINT64);
+ g_value_set_uint64 (&a_value, a);
+
+ g_value_init (&b_value, G_TYPE_UINT64);
+ g_value_copy (&a_value, &b_value);
+
+ b = g_value_get_uint64 (&b_value);
+
+ if (a == b) {
+ g_print ("Yay !! 10 lines of code to copy around a uint64.\n");
+ } else {
+ g_print ("Are you sure this is not a Z80 ?\n");
+ }
+}
+
+static void test_object (void)
+{
+ GObject *obj;
+ GValue obj_vala = {0, };
+ GValue obj_valb = {0, };
+ obj = g_object_new (MAMAN_BAR_TYPE, NULL);
+
+ g_value_init (&obj_vala, MAMAN_BAR_TYPE);
+ g_value_set_object (&obj_vala, obj);
+
+ g_value_init (&obj_valb, G_TYPE_OBJECT);
+
+ /* g_value_copy's semantics for G_TYPE_OBJECT types is to copy the reference.
+ This function thus calls g_object_ref.
+ It is interesting to note that the assignment works here because
+ MAMAN_BAR_TYPE is a G_TYPE_OBJECT.
+ */
+ g_value_copy (&obj_vala, &obj_valb);
+
+ g_object_unref (G_OBJECT (obj));
+ g_object_unref (G_OBJECT (obj));
+}
+</programlisting>
+ The important point about the above code is that the exact semantic of the copy calls
+ is undefined since they depend on the implementation of the copy function. Certain
+ copy functions might decide to allocate a new chunk of memory and then to copy the
+ data from the source to the destination. Others might want to simply increment
+ the reference count of the instance and copy the reference to the new GValue.
+ </para>
+
+ <para>
+ The value_table used to specify these assignment functions is defined in
+ <filename>gtype.h</filename> and is thoroughly described in the
+ API documentation provided with GObject (for once ;-) which is why we will
+ not detail its exact semantics.
+ <programlisting>
+typedef struct _GTypeValueTable GTypeValueTable;
+struct _GTypeValueTable
+{
+ void (*value_init) (GValue *value);
+ void (*value_free) (GValue *value);
+ void (*value_copy) (const GValue *src_value,
+ GValue *dest_value);
+ /* varargs functionality (optional) */
+ gpointer (*value_peek_pointer) (const GValue *value);
+ gchar *collect_format;
+ gchar* (*collect_value) (GValue *value,
+ guint n_collect_values,
+ GTypeCValue *collect_values,
+ guint collect_flags);
+ gchar *lcopy_format;
+ gchar* (*lcopy_value) (const GValue *value,
+ guint n_collect_values,
+ GTypeCValue *collect_values,
+ guint collect_flags);
+};
+ </programlisting>
+ Interestingly, it is also very unlikely
+ you will ever need to specify a value_table during type registration
+ because these value_tables are inherited from the parent types for
+ non-fundamental types which means that unless you want to write a
+ fundamental type (not a great idea !), you will not need to provide
+ a new value_table since you will inherit the value_table structure
+ from your parent type.
+ </para>
+ </sect1>
+
+ <sect1 id="gtype-conventions">
+ <title>Conventions</title>
+
+
+ <para>
+ There are a number of conventions users are expected to follow when creating new types
+ which are to be exported in a header file:
+ <itemizedlist>
+ <listitem><para>
+ Use the <function>object_method</function> pattern for function names: to invoke
+ the method named foo on an instance of object type bar, call
+ <function>bar_foo</function>.
+ </para></listitem>
+ <listitem><para>Use prefixing to avoid namespace conflicts with other projects.
+ If your library (or application) is named <emphasis>Maman</emphasis>,
+ prefix all your function names with <emphasis>maman_</emphasis>.
+ For example: <function>maman_object_method</function>.
+ </para></listitem>
+ <listitem><para>Create a macro named <function>PREFIX_OBJECT_TYPE</function> which always
+ returns the Gtype for the associated object type. For an object of type
+ <emphasis>Bar</emphasis> in a libray prefixed by <emphasis>maman</emphasis>,
+ use: <function>MAMAN_BAR_TYPE</function>.
+ It is common although not a convention to implement this macro using either a global
+ static variable or a function named <function>prefix_object_get_type</function>.
+ We will follow the function pattern wherever possible in this document.
+ </para></listitem>
+ <listitem><para>Create a macro named <function>PREFIX_OBJECT (obj)</function> which
+ returns a pointer of type <type>PrefixObject</type>. This macro is used to enforce
+ static type safety by doing explicit casts wherever needed. It also enforces
+ dynamic type safety by doing runtime checks. It is expected that in production
+ builds, the dynamic type checks are disabled: they should be used only in
+ development environments. For example, we would create
+ <function>MAMAN_BAR (obj)</function> to keep the previous example.
+ </para></listitem>
+ <listitem><para>If the type is classed, create a macro named
+ <function>PREFIX_OBJECT_CLASS (klass)</function>. This macro
+ is strictly equivalent to the previous casting macro: it does static casting with
+ dynamic type checking of class structures. It is expected to return a pointer
+ to a class structure of type <type>PrefixObjectClass</type>. Again, an example is:
+ <function>MAMAN_BAR_CLASS</function>.</para></listitem>
+ <listitem><para>Create a macro named <function>PREFIX_IS_BAR (obj)</function>: this macro is expected
+ to return a <type>gboolean</type> which indicates whether or not the input
+ object instance pointer of type BAR.</para></listitem>
+ <listitem><para>If the type is classed, create a macro named
+ <function>PREFIX_IS_OBJECT_CLASS (klass)</function> which, as above, returns a boolean
+ if the input class pointer is a pointer to a class of type OBJECT.
+ </para></listitem>
+ <listitem><para>If the type is classed, create a macro named
+ <function>PREFIX_OBJECT_GET_CLASS (obj)</function>
+ which returns the class pointer associated to an instance of a given type. This macro
+ is used for static and dynamic type safety purposes (just like the previous casting
+ macros).</para></listitem>
+ </itemizedlist>
+ The implementation of these macros is pretty straightforward: a number of simple-to-use
+ macros are provided in <filename>gtype.h</filename>. For the example we used above, we would
+ write the following trivial code to declare the macros:
+<programlisting>
+#define MAMAN_BAR_TYPE (maman_bar_get_type ())
+#define MAMAN_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_BAR_TYPE, MamanBar))
+#define MAMAN_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MAMAN_BAR_TYPE, MamanBarClass))
+#define MAMAN_IS_BAR(obj) (G_TYPE_CHECK_TYPE ((obj), MAMAN_BAR_TYPE))
+#define MAMAN_IS_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MAMAN_BAR_TYPE))
+#define MAMAN_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MAMAN_BAR_TYPE, MamanBarClass))
+</programlisting>
+ </para>
+
+ <para>
+ The following code shows how to implement the <function>maman_bar_get_type</function>
+ function:
+<programlisting>
+GType maman_bar_get_type (void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ /* You fill this structure. */
+ };
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "MamanBarType",
+ &info, 0);
+ }
+ return type;
+}
+</programlisting>
+ </para>
+
+ </sect1>
+
+ <sect1 id="gtype-non-instantiable">
+ <title>Non-Instantiable non-classed fundamental types</title>
+
+ <para>
+ A lot of types are not instantiable by the type system and do not have
+ a class. Most of these types are fundamental trivial types such as <emphasis>gchar</emphasis>,
+ registered in <function>g_value_types_init</function> (in <filename>gvaluetypes.c</filename>).
+ </para>
+
+ <para>
+ To register such a type in the type system, you just need to fill the
+ <type>GTypeInfo</type> structure with zeros since these types are also most of the time
+ fundamental:
+ <programlisting>
+ GTypeInfo info = {
+ 0, /* class_size */
+ NULL, /* base_init */
+ NULL, /* base_destroy */
+ NULL, /* class_init */
+ NULL, /* class_destroy */
+ NULL, /* class_data */
+ 0, /* instance_size */
+ 0, /* n_preallocs */
+ NULL, /* instance_init */
+ NULL, /* value_table */
+ };
+ static const GTypeValueTable value_table = {
+ value_init_long0, /* value_init */
+ NULL, /* value_free */
+ value_copy_long0, /* value_copy */
+ NULL, /* value_peek_pointer */
+ "i", /* collect_format */
+ value_collect_int, /* collect_value */
+ "p", /* lcopy_format */
+ value_lcopy_char, /* lcopy_value */
+ };
+ info.value_table = &value_table;
+ type = g_type_register_fundamental (G_TYPE_CHAR, "gchar", &info, &finfo, 0);
+ </programlisting>
+ </para>
+
+
+ <para>
+ Having non-instantiable types might seem a bit useless: what good is a type
+ if you cannot instanciate an instance of that type ? Most of these types
+ are used in conjunction with <type>GValue</type>s: a GValue is initialized
+ with an integer or a string and it is passed around by using the registered
+ type's value_table. <type>GValue</type>s (and by extension these trivial fundamental
+ types) are most useful when used in conjunction with object properties and signals.
+ </para>
+
+ </sect1>
+
+ <sect1 id="gtype-instantiable-classed">
+ <title>Instantiable classed types: objects</title>
+
+ <para>
+ Types which are registered with a class and are declared instantiable are
+ what most closely resembles an <emphasis>object</emphasis>. The code below
+ shows how you could register such a type in the type system:
+<programlisting>
+typedef struct {
+ Object parent;
+ /* instance members */
+ int field_a;
+} MamanBar;
+
+struct _MamanBarClass {
+ GObjectClass parent;
+ /* class members */
+ void (*do_action_public_virtual) (MamanBar *self, guint8 i);
+
+ void (*do_action_public_pure_virtual) (MamanBar *self, guint8 i);
+};
+
+#define MAMAN_BAR_TYPE (maman_bar_get_type ())
+
+GType
+maman_bar_get_type (void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (MamanBarClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) foo_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (MamanBar),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL /* instance_init */
+ };
+ type = g_type_register_fundamental (G_TYPE_OBJECT,
+ "BarType",
+ &info, 0);
+ }
+ return type;
+}
+</programlisting>
+ Upon the first call to <function>maman_bar_get_type</function>, the type named
+ <emphasis>BarType</emphasis> will be registered in the type system as inheriting
+ from the type <emphasis>G_TYPE_OBJECT</emphasis>.
+ </para>
+
+ <para>
+ Every object must define two structures: its class structure and its
+ instance structure. All class structures must contain as first member
+ a <type>GTypeClass</type> structure. All instance structures must contain as first
+ member a <type>GTypeInstance</type> structure. The declaration of these C types,
+ coming from <filename>gtype.h</filename> is shown below:
+<programlisting>
+struct _GTypeClass
+{
+ GType g_type;
+};
+struct _GTypeInstance
+{
+ GTypeClass *g_class;
+};
+</programlisting>
+ These constraints allow the type system to make sure that every object instance
+ (identified by a pointer to the object's instance structure) contains in its
+ first bytes a pointer to the object's class structure.
+ </para>
+ <para>
+ This relationship is best explained by an example: let's take object B which
+ inherits from object A:
+<programlisting>
+/* A definitions */
+typedef struct {
+ GTypeInstance parent;
+ int field_a;
+ int field_b;
+} A;
+typedef struct {
+ GTypeClass parent_class;
+ void (*method_a) (void);
+ void (*method_b) (void);
+} AClass;
+
+/* B definitions. */
+typedef struct {
+ A parent;
+ int field_c;
+ int field_d;
+} B;
+typedef struct {
+ AClass parent_class;
+ void (*method_c) (void);
+ void (*method_d) (void);
+} BClass;
+</programlisting>
+ The C standard mandates that the first field of a C structure is stored starting
+ in the first byte of the buffer used to hold the structure's fields in memory.
+ This means that the first field of an instance of an object B is A's first field
+ which in turn is GTypeInstance's first field which in turn is g_class, a pointer
+ to B's class structure.
+ </para>
+
+ <para>
+ Thanks to these simple conditions, it is possible to detect the type of every
+ object instance by doing:
+<programlisting>
+B *b;
+b->parent.parent_class->g_class.g_type
+</programlisting>
+ or, more quickly:
+<programlisting>
+B *b;
+((GTypeInstance*)b)->g_class.g_type
+</programlisting>
+ </para>
+
+ <para>
+ Instanciation of these types can be done with <function>g_type_create_instance</function>:
+<programlisting>
+GTypeInstance* g_type_create_instance (GType type);
+void g_type_free_instance (GTypeInstance *instance);
+</programlisting>
+ <function>g_type_create_instance</function> will lookup the type information
+ structure associated to the type requested. Then, the instance size and instanciation
+ policy (if the n_preallocs field is set to a non-zero value, the type system allocates
+ the object's instance structures in chunks rather than mallocing for every instance)
+ declared by the user are used to get a buffer to hold the object's instance
+ structure.
+ </para>
+
+ <para>
+ If this is the first instance of the object ever created, the type system must create
+ a class structure: it allocates a buffer to hold the object's class structure and
+ initializes it. It first copies the parent's class structure over this structure
+ (if there is no parent, it initializes it to zero). It then invokes the
+ base_class_initialization functions (<type>GBaseInitFunc</type>) from topmost
+ fundamental object to bottom-most most derived object. The object's class_init
+ (<type>GClassInitFunc</type>) function is invoked afterwards to complete
+ initialization of the class structure.
+ Finally, the object's interfaces are initialized (we will discuss interface initialization
+ in more detail later).
+<footnote id="class-init">
+<para>
+The class initialization process is entirely implemented in
+<function>type_class_init_Wm</function> in <filename>gtype.c</filename>.
+</para>
+</footnote>
+ </para>
+
+ <para>
+ Once the type system has a pointer to an initialized class structure, it sets the object's
+ instance class pointer to the object's class structure and invokes the object's
+ instance_init (<type>GInstanceInitFunc</type>)functions, from top-most fundamental
+ type to bottom-most most derived type.
+ </para>
+
+ <para>
+ Object instance destruction through <function>g_type_free_instance</function> is very simple:
+ the instance structure is returned to the instance pool if there is one and if this was the
+ last living instance of the object, the class is destroyed.
+ </para>
+
+ <para>
+ Class destruction (called finalization in Gtype) is the symmetric process of the initialization:
+ it is implemented in <function>type_data_finalize_class_U</function> (in <filename>gtype.c
+ </filename>, as usual...). Interfaces are first destroyed. Then, the most derived
+ class_finalize (<type>ClassFinalizeFunc</type>) function is invoked. The
+ base_class_finalize (<type>GBaseFinalizeFunc</type>) functions are
+ Finally invoked from bottom-most most-derived type to top-most fundamental type and
+ the class structure is freed.
+ </para>
+
+ <para>
+ As many readers have now understood it, the base initialization/finalization process is
+ very similar to the C++ Constructor/Destructor paradigm. However, it is very different
+ in that, in C++, class constructors are automatically edited at compile
+ time by the compiler to ensure that classes are correctly initialized before
+ running the user-provided constructor code itself. With GObject, users must provide both
+ the class and instance initialization functions.
+ Similarly, GTypes have no instance destruction mechanism. It is
+ the user's responsibility to implement correct destruction semantics on top
+ of the existing GType code. (this is what GObject does. See
+ <xref linkend="chapter-gobject"></xref>)
+ </para>
+
+ <para>
+ The instanciation/finalization process can be summarized as follows:
+ <table>
+ <title>GType Instantiation/Finalization</title>
+ <tgroup cols="3">
+ <colspec colwidth="*" colnum="1" align="left"/>
+ <colspec colwidth="*" colnum="2" align="left"/>
+ <colspec colwidth="8*" colnum="3" align="left"/>
+
+ <thead>
+ <row>
+ <entry>Invocation time</entry>
+ <entry>Function Invoked</entry>
+ <entry>Function's parameters</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>First call to <function>g_type_create_instance</function> for target type</entry>
+ <entry>type's base_init function</entry>
+ <entry>On the inheritance tree of classes from fundamental type to target type.
+ base_init is invoked once for each class structure.</entry>
+ </row>
+ <row>
+ <entry>First call to <function>g_type_create_instance</function> for target type</entry>
+ <entry>target type's class_init function</entry>
+ <entry>On target type's class structure</entry>
+ </row>
+ <row>
+ <entry>First call to <function>g_type_create_instance</function> for target type</entry>
+ <entry colspan="2">interface initialization, see
+ <xref linkend="gtype-non-instantiable-classed-init"></xref></entry>
+ </row>
+ <row>
+ <entry>Each call to <function>g_type_create_instance</function> for target type</entry>
+ <entry>target type's instance_init function</entry>
+ <entry>On object's instance</entry>
+ </row>
+ <row>
+ <entry>Last call to <function>g_type_free_instance</function> for target type</entry>
+ <entry colspan="2">interface destruction, see
+ <xref linkend="gtype-non-instantiable-classed-dest"></xref></entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>Last call to <function>g_type_free_instance</function> for target type</entry>
+ <entry>target type's class_finalize function</entry>
+ <entry>On target type's class structure</entry>
+ </row>
+ <row>
+ <entry>Last call to <function>g_type_free_instance</function> for target type</entry>
+ <entry>type's base_finalize function</entry>
+ <entry>On the inheritance tree of classes from fundamental type to target type.
+ base_init is invoked once for each class structure.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </para>
+
+ </sect1>
+
+ <sect1 id="gtype-non-instantiable-classed">
+ <title>Non-instantiable classed types: Interfaces.</title>
+
+ <para>
+ GType's Interfaces are very similar to Java's interfaces. To declare one of these
+ you have to register a non-instantiable classed type which derives from
+ GTypeInterface. The following piece of code declares such an interface.
+<programlisting>
+#define MAMAN_IBAZ_TYPE (maman_ibaz_get_type ())
+#define MAMAN_IBAZ(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_IBAZ_TYPE, MamanIbaz))
+#define MAMAN_IBAZ_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), MAMAN_IBAZ_TYPE, MamanIbazClass))
+#define MAMAN_IS_IBAZ(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_IBAZ_TYPE))
+#define MAMAN_IS_IBAZ_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MAMAN_IBAZ_TYPE))
+#define MAMAN_IBAZ_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), MAMAN_IBAZ_TYPE, MamanIbazClass))
+
+typedef struct _MamanIbaz MamanIbaz; /* dummy object */
+typedef struct _MamanIbazClass MamanIbazClass;
+
+struct _MamanIbazClass {
+ GTypeInterface parent;
+
+ void (*do_action) (MamanIbaz *self);
+};
+
+GType maman_ibaz_get_type (void);
+
+void maman_ibaz_do_action (MamanIbaz *self);
+</programlisting>
+ The interface function, <function>maman_ibaz_do_action</function> is implemented
+ in a pretty simple way:
+<programlisting>
+void maman_ibaz_do_action (MamanIbaz *self)
+{
+ MAMAN_IBAZ_GET_CLASS (self)->do_action (self);
+}
+</programlisting>
+ <function>maman_ibaz_get_gtype</function> registers a type named <emphasis>MamanIBaz</emphasis>
+ which inherits from G_TYPE_INTERFACE. All interfaces must be children of G_TYPE_INTERFACE in the
+ inheritance tree.
+ </para>
+
+ <para>
+ An interface is defined by only one structure which must contain as first member
+ a <type>GTypeInterface</type> structure. The interface structure is expected to
+ contain the function pointers of the interface methods. It is good style to
+ define helper functions for each of the interface methods which simply call
+ the interface' method directly: <function>maman_ibaz_do_action</function>
+ is one of these.
+ </para>
+
+ <para>
+ Once an interface type is registered, you must register implementations for these
+ interfaces. The function named <function>maman_baz_get_type</function> registers
+ a new GType named MamanBaz which inherits from <type>GObject</type> and which
+ implements the interface <type>MamanIBaz</type>.
+<programlisting>
+static void maman_baz_do_action (MamanIbaz *self)
+{
+ g_print ("Baz implementation of IBaz interface Action.\n");
+}
+
+
+static void
+baz_interface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ MamanIbazClass *klass = (MamanIbazClass *)g_iface;
+ klass->do_action = maman_baz_do_action;
+}
+
+GType
+maman_baz_get_type (void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (MamanBazClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (MamanBaz),
+ 0, /* n_preallocs */
+ NULL /* instance_init */
+ };
+ static const GInterfaceInfo ibaz_info = {
+ (GInterfaceInitFunc) baz_interface_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ };
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "MamanBazType",
+ &info, 0);
+ g_type_add_interface_static (type,
+ MAMAN_IBAZ_TYPE,
+ &ibaz_info);
+ }
+ return type;
+}
+</programlisting>
+ </para>
+
+ <para>
+ <function>g_type_add_interface_static</function> records in the type system that
+ a given type implements also <type>FooInterface</type>
+ (<function>foo_interface_get_type</function> returns the type of
+ <type>FooInterface</type>). The <type>GInterfaceInfo</type> structure holds
+ information about the implementation of the interface:
+<programlisting>
+struct _GInterfaceInfo
+{
+ GInterfaceInitFunc interface_init;
+ GInterfaceFinalizeFunc interface_finalize;
+ gpointer interface_data;
+};
+</programlisting>
+ </para>
+
+ <sect2 id="gtype-non-instantiable-classed-init">
+ <title>Interface Initialization</title>
+
+ <para>
+ When an instantiable classed type which registered an interface implementation
+ is created for the first time, its class structure is initialized following the process
+ described in <xref linkend="gtype-instantiable-classed"></xref>. Once the class structure is
+ initialized,the function <function>type_class_init_Wm</function> (implemented in <filename>
+ gtype.c</filename>) initializes the interface implementations associated with
+ that type by calling <function>type_iface_vtable_init_Wm</function> for each
+ interface.
+ </para>
+
+ <para>
+ First a memory buffer is allocated to hold the interface structure. The parent's
+ interface structure is then copied over to the new interface structure (the parent
+ interface is already initialized at that point). If there is no parent interface,
+ the interface structure is initialized with zeros. The g_type and the g_instance_type
+ fields are then initialized: g_type is set to the type of the most-derived interface
+ and g_instance_type is set to the type of the most derived type which implements
+ this interface.
+ </para>
+
+ <para>
+ Finally, the interface' most-derived <function>base_init</function> function and then
+ the implementation's <function>interface_init</function>
+ function are invoked. It is important to understand that if there are multiple
+ implementations of an interface the <function>base_init</function> and
+ <function>interface_init</function> functions will be
+ invoked once for each implementation initialized.
+ </para>
+
+ <para>
+ It is thus common for base_init functions to hold a local static boolean variable
+ which makes sure that the interface type is initialized only once even if there are
+ multiple implementations of the interface:
+<programlisting>
+static void
+maman_ibaz_base_init (gpointer g_class)
+{
+ static gboolean initialized = FALSE;
+
+ if (!initialized) {
+ /* create interface signals here. */
+ initialized = TRUE;
+ }
+}
+</programlisting>
+ </para>
+
+ <para>
+ If you have found the stuff about interface hairy, you are right: it is hairy but
+ there is not much I can do about it. What I can do is summarize what you need to know
+ about interfaces:
+ </para>
+
+ <para>
+ The above process can be summarized as follows:
+ <table>
+ <title><function>Interface Initialization</function></title>
+ <tgroup cols="3">
+ <colspec colwidth="*" colnum="1" align="left"/>
+ <colspec colwidth="*" colnum="2" align="left"/>
+ <colspec colwidth="8*" colnum="3" align="left"/>
+
+ <thead>
+ <row>
+ <entry>Invocation time</entry>
+ <entry>Function Invoked</entry>
+ <entry>Function's parameters</entry>
+ <entry>Remark</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>First call to <function>g_type_create_instance</function> for type
+ implementing interface</entry>
+ <entry>interface' base_init function</entry>
+ <entry>On interface' vtable</entry>
+ <entry>Register interface' signals here (use a local static
+ boolean variable as described above to make sure not to register them
+ twice.).</entry>
+ </row>
+ <row>
+ <entry>First call to <function>g_type_create_instance</function> for type
+ implementing interface</entry>
+ <entry>interface' interface_init function</entry>
+ <entry>On interface' vtable</entry>
+ <entry>
+ Initialize interface' implementation. That is, initialize the interface
+ method pointers in the interface structure to the function's implementation.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ It is highly unlikely (ie: I do not know of <emphasis>anyone</emphasis> who actually
+ used it) you will ever need other more fancy things such as the ones described in the
+ following section (<xref linkend="gtype-non-instantiable-classed-dest"></xref>).
+ </para>
+
+ </sect2>
+
+ <sect2 id="gtype-non-instantiable-classed-dest">
+ <title>Interface Destruction</title>
+
+ <para>
+ When the last instance of an instantiable type which registered an interface implementation
+ is destroyed, the interface's implementations associated to the type are destroyed by
+ <function>type_iface_vtable_finalize_Wm</function> (in <filename>gtype.c</filename>).
+ </para>
+
+ <para>
+ <function>type_iface_vtable_finalize_Wm</function> invokes first the implementation's
+ <function>interface_finalize</function> function and then the interface's most-derived
+ <function>base_finalize</function> function.
+ </para>
+
+ <para>
+ Again, it is important to understand, as in
+ <xref linkend="gtype-non-instantiable-classed-init"></xref>,
+ that both <function>interface_finalize</function> and <function>base_finalize</function>
+ are invoked exactly once for the destruction of each implementation of an interface. Thus,
+ if you were to use one of these functions, you would need to use a static integer variable
+ which would hold the number of instances of implementations of an interface such that
+ the interface's class is destroyed only once (when the integer variable reaches zero).
+ </para>
+
+ <para>
+ The above process can be summarized as follows:
+ <table>
+ <title><function>Interface Finalization</function></title>
+ <tgroup cols="3">
+ <colspec colwidth="*" colnum="1" align="left"/>
+ <colspec colwidth="*" colnum="2" align="left"/>
+ <colspec colwidth="8*" colnum="3" align="left"/>
+
+ <thead>
+ <row>
+ <entry>Invocation time</entry>
+ <entry>Function Invoked</entry>
+ <entry>Function's parameters</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>Last call to <function>g_type_free_instance</function> for type
+ implementing interface</entry>
+ <entry>interface' interface_finalize function</entry>
+ <entry>On interface' vtable</entry>
+ </row>
+ <row>
+ <entry>Last call to <function>g_type_free_instance</function>for type
+ implementing interface</entry>
+ <entry>interface' base_finalize function</entry>
+ <entry>On interface' vtable</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </para>
+
+ <para>
+ Now that you have read this section, you can forget about it. Please, forget it
+ <emphasis>as soon as possible</emphasis>.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ </chapter>
--- /dev/null
+<chapter id="howto">
+ <title>How To ?</title>
+
+ <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>
+
+<!--
+ Howto GObject
+-->
+
+ <sect1 id="howto-gobject">
+ <title>How To define and implement a new GObject ?</title>
+
+ <para>
+ Clearly, this is one of the most common question 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. The sample source code
+ associated to this section can be found in the documentation's source tarball, in the
+ <filename>sample/gobject</filename> directory:
+ <itemizedlist>
+ <listitem><para><filename>maman-bar.{h|c}</filename>: this is the source for a object which derives from
+ <type>GObject</type> and which shows how to declare different types of methods on the object.
+ </para></listitem>
+ <listitem><para><filename>maman-subbar.{h|c}</filename>: this is the source for a object which derives from
+ <type>MamanBar</type> and which shows how to override some of its parent's methods.
+ </para></listitem>
+ <listitem><para><filename>maman-foo.{h|c}</filename>: this is the source for an object which derives from
+ <type>GObject</type> and which declares a signal.
+ </para></listitem>
+ <listitem><para><filename>test.c</filename>: this is the main source which instantiates an instance of
+ type and exercises their API.
+ </para></listitem>
+ </itemizedlist>
+ </para>
+
+ <sect2 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>
+ </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>
+ I personally like the first solution better: it makes reading file names easier for those with poor
+ eyesight like me.
+ </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 onf 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.
+ */
+
+#ifndef MAMAN_BAR_H
+#define MAMAN_BAR_H
+
+/*
+ * Potentially, include other headers on which this header depends.
+ */
+
+
+/*
+ * Type macros.
+ */
+
+typedef struct _MamanBar MamanBar;
+typedef struct _MamanBarClass MamanBarClass;
+
+struct _MamanBar {
+ GObject parent;
+ /* instance members */
+};
+
+struct _MamanBarClass {
+ GObjectClass parent;
+ /* class members */
+};
+
+/* used by MAMAN_BAR_TYPE */
+GType maman_bar_get_type (void);
+
+/*
+ * Method definitions.
+ */
+
+#endif
+</programlisting>
+ </para></listitem>
+ <listitem><para>
+ Most GTK+ types declare their private fields in the public header with a /* private */ comment,
+ relying on their user's intelligence not to try to play with these fields. Fields not marked private
+ are considered public by default. The /* protected */ comment (same semantics as those of C++)
+ is also used, mainly in the GType library, in code written by Tim Janik.
+<programlisting>
+struct _MamanBar {
+ GObject parent;
+
+ /* private */
+ int hsize;
+};
+</programlisting>
+ </para></listitem>
+ <listitem><para>
+ All of Nautilus code and a lot of Gnome libraries use private indirection members, as described
+ by Herb Sutter in his Pimpl articles (see <ulink></ulink>: Herb summarizes the different
+ issues better than I will):
+<programlisting>
+typedef struct _MamanBarPrivate MamanBarPrivate;
+struct _MamanBar {
+ GObject parent;
+
+ /* private */
+ MamanBarPrivate *priv;
+};
+</programlisting>
+ The private structure is then defined in the .c file, instantiated in the object's XXX
+ function and destroyed in the object's XXX function.
+ </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 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>
+
+ </sect2>
+
+ <sect2 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 #include "maman-bar.h" or as complicated as tens of #include lines ending with
+ #include "maman-bar.h":
+<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>
+ Implement <function>maman_bar_get_type</function> and make sure the code compiles:
+<programlisting>
+GType
+maman_bar_get_type (void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (MamanBarClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (MamanBar),
+ 0, /* n_preallocs */
+ NULL /* instance_init */
+ };
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "MamanBarType",
+ &info, 0);
+ }
+ return type;
+}
+</programlisting>
+ </para>
+ </sect2>
+
+ <sect2 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 instanciation 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>g_object_new></function>
+ until all the construction properties have been set.
+ </para>
+
+ <para>
+ As such, I would recommend writing the following code first:
+<programlisting>
+static void
+maman_bar_init (GTypeInstance *instance,
+ gpointer g_class)
+{
+ MamanBar *self = (MamanBar *)instance;
+ self->private = g_new0 (MamanBarPrivate, 1);
+
+ /* initialize all public and private members to reasonable default values. */
+ /* If you need specific consruction properties to complete initialization,
+ * delay initialization completion until the property is set.
+ */
+}
+</programlisting>
+ And make sure that you set <function>maman_bar_init</function> as the type's instance_init function
+ in <function>maman_bar_get_type</function>. Make sure the code builds and runs: create an instance
+ of the object and make sure <function>maman_bar_init</function> is called (add a
+ <function>g_print</function> call in it).
+ </para>
+
+ <para>
+ Now, if you need special construction properties, install the properties in the class_init function,
+ override the set and get methods and implement the get and set methods as described in
+ <xref linkend="gobject-properties"/>. Make sure that these properties use a construct only
+ pspec by setting the param spec's flag field to G_PARAM_CONSTRUCT_ONLY: this helps
+ GType ensure that these properties are not set again later by malicious user code.
+<programlisting>
+static void
+bar_class_init (MamanBarClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GParamSpec *maman_param_spec;
+
+ gobject_class->set_property = bar_set_property;
+ gobject_class->get_property = bar_get_property;
+
+ maman_param_spec = 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_object_class_install_property (gobject_class,
+ PROP_MAMAN,
+ maman_param_spec);
+}
+</programlisting>
+ If you need this, make sure you can build and run code similar to the code shown above. Make sure
+ your construct properties can set correctly during construction, make sure you cannot set them
+ afterwards and make sure that if your users do not call <function>g_object_new</function>
+ with the required construction properties, these will be initialized with the default values.
+ </para>
+
+ <para>
+ I consider good taste to halt program execution if a construction property is set its
+ default value. This allows you to catch client code which does not give a reasonable
+ value to the construction properties. Of course, you are free to disagree but you
+ should have a good reason to do so.
+ </para>
+
+ <para>Some people sometimes need to construct their object but only after the construction properties
+ have been set. This is possible through the use of the constructor class method as described in
+ <xref linkend="gobject-instanciation"/>. However, I have yet to see <emphasis>any</emphasis> reasonable
+ use of this feature. As such, to initialize your object instances, use by default the base_init function
+ and construction properties.
+ </para>
+ </sect2>
+
+ <sect2 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>g_object_unref</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 must be split is two different phases: you must override
+ both the dispose and the finalize class methods.
+<programlisting>
+struct _MamanBarPrivate {
+ gboolean dispose_has_run;
+};
+
+static void
+bar_dispose (MamanBar *self)
+{
+ if (self->private->dispose_has_run) {
+ /* If dispose did already run, return. */
+ return;
+ }
+ /* Make sure dispose does not run twice. */
+ object->private->dispose_has_run = TRUE;
+
+ /*
+ * 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.
+ */
+}
+
+static void
+bar_finalize (MamanBar *self)
+{
+ /*
+ * Here, complete object destruction.
+ * You might not need to do much...
+ */
+ g_free (self->private);
+}
+
+static void
+bar_class_init (BarClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = bar_dispose;
+ gobject_class->finalize = bar_finalize;
+}
+
+static void
+maman_bar_init (GTypeInstance *instance,
+ gpointer g_class)
+{
+ MamanBar *self = (MamanBar *)instance;
+ self->private = g_new0 (MamanBarPrivate, 1);
+ self->private->dispose_has_run = FALSE;
+}
+</programlisting>
+ </para>
+
+ <para>
+ Add similar code to your GObject, make sure the code still builds and runs: dispose and finalize must be called
+ during the last unref.
+ 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. To do this, you need something like the following code at the start of each object method, to make
+ sure the object's data is still valid before manipulating it:
+<programlisting>
+if (self->private->dispose_has_run) {
+ /* Dispose has run. Data is not valid anymore. */
+ return;
+}
+</programlisting>
+ </para>
+ </sect2>
+
+ <sect2 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++ buzzwords. Those who have not had to
+ write C++ code recently can refer to <ulink>XXXX</ulink> 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>
+
+ <sect3>
+ <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 */)
+{
+ /* do stuff here. */
+}
+</programlisting>
+ </para>
+
+ <para>There is really nothing scary about this.</para>
+ </sect3>
+
+ <sect3>
+ <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;
+
+ /* 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 */)
+{
+ MAMAN_BAR_GET_CLASS (self)->do_action (self, /* parameters */);
+}
+</programlisting>
+ The code above simply redirects the do_action call to the relevant class function. Some users,
+ concerned about performance, do not provide the <function>maman_bar_do_action</function>
+ wrapper function and require users to de-reference the class pointer themselves. This is not such
+ a great idea in terms of encapsulation and makes it difficult to change the object's implementation
+ afterwards, should this be needed.
+ </para>
+
+ <para>
+ Other users, also concerned by performance issues, declare the <function>maman_bar_do_action</function>
+ function inline in the header file. This, however, makes it difficult to change the
+ object's implementation later (although easier than requiring users to directly de-reference the class
+ function) and is often difficult to write in a portable way (the <emphasis>inline</emphasis> keyword
+ is not part of the C standard).
+ </para>
+
+ <para>
+ In doubt, unless a user shows you hard numbers about the performance cost of the function call,
+ just <function>maman_bar_do_action</function> in the source file.
+ </para>
+
+ <para>
+ Please, note that it is possible for you to provide a default implementation for this class method in
+ the object's class_init function: initialize the klass->do_action field to a pointer to the actual
+ implementation. You can also make this class method pure virtual by initializing the klass->do_action
+ field to NULL:
+<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)
+{
+ /* 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 */)
+{
+ MAMAN_BAR_GET_CLASS (self)->do_action_one (self, /* parameters */);
+}
+void maman_bar_do_action_two (MamanBar *self, /* parameters */)
+{
+ MAMAN_BAR_GET_CLASS (self)->do_action_two (self, /* parameters */);
+}
+</programlisting>
+ </para>
+ </sect3>
+
+ <sect3>
+ <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>
+
+ <para>
+ Finally, it is interesting to note that, just like in C++, it is possible
+ to make each object class method chain to its parent class method:
+<programlisting>
+static void
+maman_bar_real_do_action_two (MamanBar *self, /* parameters */)
+{
+ MamanBarClass *bar_class = g_type_class_peek_parent (klass);
+ /* chain up */
+ bar_class->do_action (self, /* parameters */);
+
+ /* do local stuff here. */
+}
+
+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>
+ </sect3>
+ </sect2>
+
+
+ </sect1>
+
+<!--
+ End Howto GObject
+-->
+
+
+<!--
+ Howto Interfaces
+-->
+
+ <sect1 id="howto-interface">
+ <title>How To define and implement Interfaces ?</title>
+
+ <sect2 id="howto-interface-define">
+ <title>How To define 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. The sample source code
+ associated to this section can be found in the documentation's source tarball, in the
+ <filename>sample/interface/maman-ibaz.{h|c}</filename> file.
+ </para>
+
+ <para>
+ As above, the first step is to get the header right:
+<programlisting>
+#ifndef MAMAN_IBAZ_H
+#define MAMAN_IBAZ_H
+
+#include <glib-object.h>
+
+#define MAMAN_IBAZ_TYPE (maman_ibaz_get_type ())
+#define MAMAN_IBAZ(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_IBAZ_TYPE, MamanIbaz))
+#define MAMAN_IBAZ_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), MAMAN_IBAZ_TYPE, MamanIbazClass))
+#define MAMAN_IS_IBAZ(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_IBAZ_TYPE))
+#define MAMAN_IS_IBAZ_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MAMAN_IBAZ_TYPE))
+#define MAMAN_IBAZ_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), MAMAN_IBAZ_TYPE, MamanIbazClass))
+
+
+typedef struct _MamanIbaz MamanIbaz; /* dummy object */
+typedef struct _MamanIbazClass MamanIbazClass;
+
+struct _MamanIbazClass {
+ GTypeInterface parent;
+
+ void (*do_action) (MamanIbaz *self);
+};
+
+GType maman_ibaz_get_type (void);
+
+void maman_ibaz_do_action (MamanIbaz *self);
+
+#endif //MAMAN_IBAZ_H
+</programlisting>
+ This code is almost exactly similar to the code for a normal <type>GType</type>
+ which derives from a <type>GObject</type> except for a few details:
+ <itemizedlist>
+ <listitem><para>
+ The <function>_GET_CLASS</function> macro is not implemented with
+ <function>G_TYPE_INSTANCE_GET_CLASS</function> but with <function>G_TYPE_INSTANCE_GET_INTERFACE</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>
+ </itemizedlist>
+ </para>
+
+ <para>
+ The implementation of the <type>MamanIbaz</type> type itself is trivial:
+ <itemizedlist>
+ <listitem><para><function>maman_ibaz_get_type</function> registers the
+ type in the type system.
+ </para></listitem>
+ <listitem><para><function>maman_ibaz_base_init</function> 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
+ <xref linkend="gtype-non-instantiable-classed-init"/>,
+ <function>base_init</function> is run once for each interface implementation
+ instanciation)</para></listitem>
+ <listitem><para><function>maman_ibaz_do_action</function> de-references the class
+ structure to access its associated class function and calls it.
+ </para></listitem>
+ </itemizedlist>
+<programlisting>
+static void
+maman_ibaz_base_init (gpointer g_class)
+{
+ static gboolean initialized = FALSE;
+
+ if (!initialized) {
+ /* create interface signals here. */
+ initialized = TRUE;
+ }
+}
+
+GType
+maman_ibaz_get_type (void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (MamanIbazClass),
+ maman_ibaz_base_init, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ 0,
+ 0, /* n_preallocs */
+ NULL /* instance_init */
+ };
+ type = g_type_register_static (G_TYPE_INTERFACE, "MamanIbaz", &info, 0);
+ }
+ return type;
+}
+
+void maman_ibaz_do_action (MamanIbaz *self)
+{
+ MAMAN_IBAZ_GET_CLASS (self)->do_action (self);
+}
+</programlisting>
+ </para>
+ </sect2>
+
+ <sect2 id="howto-interface-implement">
+ <title>How To define and implement an implementation of an Interface ?</title>
+
+ <para>
+ Once the interface is defined, implementing it is rather trivial. Source code showing how to do this
+ for the <type>IBaz</type> interface defined in the previous section is located in
+ <filename>sample/interface/maman-baz.{h|c}</filename>.
+ </para>
+
+ <para>
+ The first step is to define a normal GType. Here, we have decided to use a GType which derives from
+ GObject. Its name is <type>MamanBaz</type>:
+<programlisting>
+#ifndef MAMAN_BAZ_H
+#define MAMAN_BAZ_H
+
+#include <glib-object.h>
+
+#define MAMAN_BAZ_TYPE (maman_baz_get_type ())
+#define MAMAN_BAZ(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_BAZ_TYPE, Mamanbaz))
+#define MAMAN_BAZ_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), MAMAN_BAZ_TYPE, MamanbazClass))
+#define MAMAN_IS_BAZ(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_BAZ_TYPE))
+#define MAMAN_IS_BAZ_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MAMAN_BAZ_TYPE))
+#define MAMAN_BAZ_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), MAMAN_BAZ_TYPE, MamanbazClass))
+
+
+typedef struct _MamanBaz MamanBaz;
+typedef struct _MamanBazClass MamanBazClass;
+
+struct _MamanBaz {
+ GObject parent;
+ int instance_member;
+};
+
+struct _MamanBazClass {
+ GObjectClass parent;
+};
+
+GType maman_baz_get_type (void);
+
+
+#endif //MAMAN_BAZ_H
+</programlisting>
+ There is clearly nothing specifically weird or scary about this header: it does not define any weird API
+ or derives from a weird type.
+ </para>
+
+ <para>
+ The second step is to implement <function>maman_baz_get_type</function>:
+<programlisting>
+GType
+maman_baz_get_type (void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (MamanBazClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (MamanBaz),
+ 0, /* n_preallocs */
+ baz_instance_init /* instance_init */
+ };
+ static const GInterfaceInfo ibaz_info = {
+ (GInterfaceInitFunc) baz_interface_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ };
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "MamanBazType",
+ &info, 0);
+ g_type_add_interface_static (type,
+ MAMAN_IBAZ_TYPE,
+ &ibaz_info);
+ }
+ return type;
+}
+</programlisting>
+ This function is very much like all the similar functions we looked at previously. The only interface-specific
+ code present here is the call to <function>g_type_add_interface_static</function> which is used to inform
+ the type system that this just-registered <type>GType</type> also implements the interface
+ <function>MAMAN_IBAZ_TYPE</function>.
+ </para>
+
+ <para>
+ <function>baz_interface_init</function>, the interface initialization function, is also pretty simple:
+<programlisting>
+static void baz_do_action (MamanBaz *self)
+{
+ g_print ("Baz implementation of IBaz interface Action: 0x%x.\n", self->instance_member);
+}
+static void
+baz_interface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ MamanIbazClass *klass = (MamanIbazClass *)g_iface;
+ klass->do_action = (void (*) (MamanIbaz *self))baz_do_action;
+}
+static void
+baz_instance_init (GTypeInstance *instance,
+ gpointer g_class)
+{
+ MamanBaz *self = (MamanBaz *)instance;
+ self->instance_member = 0xdeadbeaf;
+}
+</programlisting>
+ <function>baz_interface_init</function> merely initializes the interface methods to the implementations
+ defined by <type>MamanBaz</type>: <function>maman_baz_do_action</function> does nothing very useful
+ but it could :)
+ </para>
+
+</sect2>
+
+<sect2>
+ <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 interfaces 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>
+ type = g_type_register_static (G_TYPE_INTERFACE, "MamanIbar", &info, 0);
+ /* Make the MamanIbar interface require MamanIbaz interface. */
+ g_type_interface_add_prerequisite (type, MAMAN_IBAZ_TYPE);
+</programlisting>
+ The code shown above adds the MamanIbaz interface to the list of prerequisites of MamanIbar while the
+ code below shows how an implementation can implement both interfaces and register their implementations:
+<programlisting>
+static void ibar_do_another_action (MamanBar *self)
+{
+ g_print ("Bar implementation of IBar interface Another Action: 0x%x.\n", self->instance_member);
+}
+
+static void
+ibar_interface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ MamanIbarClass *klass = (MamanIbarClass *)g_iface;
+ klass->do_another_action = (void (*) (MamanIbar *self))ibar_do_another_action;
+}
+
+
+static void ibaz_do_action (MamanBar *self)
+{
+ g_print ("Bar implementation of IBaz interface Action: 0x%x.\n", self->instance_member);
+}
+
+static void
+ibaz_interface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ MamanIbazClass *klass = (MamanIbazClass *)g_iface;
+ klass->do_action = (void (*) (MamanIbaz *self))ibaz_do_action;
+}
+
+
+static void
+bar_instance_init (GTypeInstance *instance,
+ gpointer g_class)
+{
+ MamanBar *self = (MamanBar *)instance;
+ self->instance_member = 0x666;
+}
+
+
+GType
+maman_bar_get_type (void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (MamanBarClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (MamanBar),
+ 0, /* n_preallocs */
+ bar_instance_init /* instance_init */
+ };
+ static const GInterfaceInfo ibar_info = {
+ (GInterfaceInitFunc) ibar_interface_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ };
+ static const GInterfaceInfo ibaz_info = {
+ (GInterfaceInitFunc) ibaz_interface_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ };
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "MamanBarType",
+ &info, 0);
+ g_type_add_interface_static (type,
+ MAMAN_IBAZ_TYPE,
+ &ibaz_info);
+ g_type_add_interface_static (type,
+ MAMAN_IBAR_TYPE,
+ &ibar_info);
+ }
+ return type;
+}
+</programlisting>
+ It is very important to notice that the order in which interface implementations are added to the main object
+ is not random: <function>g_type_interface_static</function> must be invoked first on the interfaces which have
+ no prerequisites and then on the others.
+</para>
+
+ <para>
+ Complete source code showing how to define the MamanIbar interface which requires MamanIbaz and how to
+ implement the MamanIbar interface is located in <filename>sample/interface/maman-ibar.{h|c}</filename>
+ and <filename>sample/interface/maman-bar.{h|c}</filename>.
+ </para>
+
+</sect2>
+
+ </sect1>
+
+<!--
+ End Howto Interfaces
+-->
+
+
+<!--
+ start Howto Signals
+-->
+
+
+ <sect1 id="howto-signals">
+ <title>Howto 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.
+ </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 events which can be received by numerous clients.
+ </para>
+
+<sect2>
+<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
+uses this method. The code below shows how the user can connect a callback to the write signal. Full code
+for this simple example is located in <filename>sample/signal/maman-file.{h|c}</filename> and
+in <filename>sample/signal/test.c</filename>
+<programlisting>
+ file = g_object_new (MAMAN_FILE_TYPE, NULL);
+
+ g_signal_connect (G_OBJECT (file), "write",
+ (GCallback)write_event,
+ NULL);
+
+ maman_file_write (file, buffer, 50);
+</programlisting>
+</para>
+
+<para>
+The <type>MamanFile</type> signal is registered in the class_init function:
+<programlisting>
+ 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,
+ NULL /* class closure */,
+ NULL /* accumulator */,
+ NULL /* accu_data */,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE /* return_type */,
+ 0 /* n_params */,
+ NULL /* param_types */);
+</programlisting>
+and the signal is emited in <function>maman_file_write</function>:
+<programlisting>
+void maman_file_write (MamanFile *self, guint8 *buffer, guint32 size)
+{
+ /* First write data. */
+ /* Then, notify user of data written. */
+ g_signal_emit (self, MAMAN_FILE_GET_CLASS (self)->write_signal_id,
+ 0 /* details */,
+ NULL);
+}
+</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>
+</para>
+
+</sect2>
+
+
+<sect2>
+<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 genmarshall 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>g_signal_connect</function>
+and before all handlers connected with <function>g_signal_connect_after</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>
+
+
+ <sect3>
+ <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 unecessarily 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 extremly doubtfull 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>g_signal_newv</function>.
+ </para>
+
+ <para>For example, <function>g_signal_new</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>g_signal_new</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 initialied 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>g_signal_new</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>G_STRUCT_OFFSET</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 clutered 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>g_signal_new</function> rather than <function>g_signal_newv</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>
+
+ </sect3>
+
+
+</sect2>
+
+
+
+<sect2>
+ <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>g_signal_connect</function>,
+ <function>g_signal_connect_after</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 prefered 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>g_signal_stop_by_name</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>
+
+
+</sect2>
+
+</sect1>
+
+<!--
+ <sect3>
+ <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>g_signal_new</function> function is preferred over
+ <function>g_signal_newv</function>. When <function>g_signal_new</function>
+ is used, the default closure is exported as a class function. For example,
+ <filename>gobject.h</filename> contains the declaration of <type>GObjectClass</type>
+ 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>g_object_do_class_init</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>g_signal_new</function> creates a <type>GClosure</type> which de-references 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 de-referencing 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>
+
+ </sect3>
+-->
+
+
+<!--
+ <sect1 id="howto-doc">
+ <title>How to generate API documentation for your type ?</title>
+
+ </sect1>
+-->
+
+ </chapter>
+
+
+
+
+
--- /dev/null
+<chapter>
+<title>Introduction</title>
+
+<para>
+GObject, and its lower-level type system, GType, are used by GTK+ and most Gnome libraries to
+provide:
+<itemizedlist>
+<listitem><para>object-oriented C-based APIs and</para></listitem>
+<listitem><para>automatic transparent API bindings to other compiled
+or interpreted languages.</para></listitem>
+</itemizedlist>
+</para>
+
+<para>A lot of programmers are used to work with compiled-only or dynamically interpreted-only
+languages and do not understand the challenges associated with cross-language interoperability.
+This introduction tries to provide an insight into these challenges and describes briefly
+the solution choosen by GLib.
+</para>
+
+<sect1>
+<title>Data types and programming</title>
+
+<para>
+One could say (I have seen such definitions used in some textbooks on programming language theory)
+that a programming language is merely a way to create data types and manipulate them. Most languages
+provide a number of language-native types and a few primitives to create more complex types based
+on these primitive types.
+</para>
+
+<para>
+In C, the language provides types such as <emphasis>char</emphasis>, <emphasis>long</emphasis>,
+<emphasis>pointer</emphasis>. During compilation of C code, the compiler maps these
+language types to the compiler's target architecture machine types. If you are using a C interpreter
+(I have never seen one myself but it is possible :), the interpreter (the program which interprets
+the source code and executes it) maps the language types to the machine types of the target machine at
+runtime, during the program execution (or just before execution if it uses a Just In Time compiler engine).
+</para>
+
+<para>Perl and Python which are interpreted languages do not really provide type definitions similar
+to those used by C. Perl and Python programmers manipulate variables and the type of the variables
+is decided only upon the first assignment or upon the first use which forces a type on the variable.
+The interpreter also often provides a lot of automatic conversions from one type to the other. For example,
+in Perl, a variable which holds an integer can be automatically converted to a string given the
+required context:
+<programlisting>
+my $tmp = 10;
+print "this is an integer converted to a string:" . $tmp . "\n";
+</programlisting>
+Of course, it is also often possible to explicitely specify conversions when the default conversions provided
+by the language are not intuitive.
+</para>
+
+</sect1>
+
+<sect1>
+<title>Exporting a C API</title>
+
+<para>C APIs are defined by a set of functions and global variables which are usually exported from a
+binary. C functions have an arbitrary number of arguments and one return value. Each function is thus
+uniquely identified by the function name and the set of C types which describe the function arguments
+and return value. The global variables exported by the API are similarly identified by their name and
+their type.
+</para>
+
+<para>
+A C API is thus merely defined by a set of names to which a set of types are associated. If you know the
+function calling convention and the mapping of the C types to the machine types used by the platform you
+are on, you can resolve the name of each function to find where the code associated to this function
+is located in memory, and then construct a valid argument list for the function. Finally, all you have to
+do is triger a call to the target C function with the argument list.
+</para>
+
+<para>
+For the sake of discussion, here is a sample C function and the associated 32 bit x86
+assembly code generated by gcc on my linux box:
+<programlisting>
+static void function_foo (int foo)
+{}
+
+int main (int argc, char *argv[])
+{
+
+ function_foo (10);
+
+ return 0;
+}
+
+push $0xa
+call 0x80482f4 <function_foo>
+</programlisting>
+The assembly code shown above is pretty straightforward: the first instruction pushes
+the hexadecimal value 0xa (decimal value 10) as a 32 bit integer on the stack and calls
+<function>function_foo</function>. As you can see, C function calls are implemented by
+gcc by native function calls (this is probably the fastest implementation possible).
+</para>
+
+<para>
+Now, let's say we want to call the C function <function>function_foo</function> from
+a python program. To do this, the python interpreter needs to:
+<itemizedlist>
+<listitem><para>Find where the function is located. This means probably find the binary generated by the C compiler
+which exports this functions.</para></listitem>
+<listitem><para>Load the code of the function in executable memory.</para></listitem>
+<listitem><para>Convert the python parameters to C-compatible parameters before calling
+the function.</para></listitem>
+<listitem><para>Call the function with the right calling convention</para></listitem>
+<listitem><para>Convert the return values of the C function to python-compatible
+variables to return them to the python code.</para></listitem>
+</itemizedlist>
+</para>
+
+<para>The process described above is pretty complex and there are a lot of ways to make it entirely automatic
+and transparent to the C and the Python programmers:
+<itemizedlist>
+<listitem><para>The first solution is to write by hand a lot of glue code, once for each function exported or imported,
+which does the python to C parameter conversion and the C to python return value conversion. This glue code is then
+linked with the interpreter which allows python programs to call a python functions which delegates the work to the
+C function.</para></listitem>
+<listitem><para>Another nicer solution is to automatically generate the glue code, once for each function exported or
+imported, with a special compiler which
+reads the original function signature.</para></listitem>
+<listitem><para>The solution used by GLib is to use the GType library which holds at runtime a description of
+all the objects manipulated by the programmer. This so-called <emphasis>dynamic type</emphasis><footnote>
+<para>
+ There are numerous different implementations of dynamic type systems: all C++
+ compilers have one, Java and .NET have one too. A dynamic type system allows you
+ to get information about every instantiated object at runtime. It can be implemented
+ by a process-specific database: every new object created registers the characteristics
+ of its associated type in the type system. It can also be implemented by introspection
+ interfaces. The common point between all these different type systems and implementations
+ is that they all allow you to query for object metadata at runtime.
+</para>
+</footnote>
+
+ library is then
+used by special generic glue code to automatically convert function parameters and function caling conventions
+between different runtime domains.</para></listitem>
+</itemizedlist>
+The greatest advantage of the solution implemented by GType is that the glue code sitting at the runtime domain
+boundaries is written once: the figure below states this more clearly.
+<figure>
+ <mediaobject>
+ <imageobject> <!-- this is for HTML output -->
+ <imagedata fileref="glue.png" format="png" align="center"/>
+ </imageobject>
+ <imageobject> <!-- this is for PDF output -->
+ <imagedata fileref="glue.jpg" format="jpg" align="center"/>
+ </imageobject>
+ </mediaobject>
+</figure>
+
+Currently, there exist at least Python and Perl glue code which makes it possible to use
+C objects written with GType directly in Python or Perl, without any further work.
+</para>
+
+
+</sect1>
+
+
+</chapter>