Format XML to be more editable. Describe Interfaces better. Add a footnote

* gobject/tut_gobject.xml:
* gobject/tut_gsignal.xml:
* gobject/tut_gtype.xml:
* gobject/tut_howto.xml:
* gobject/tut_intro.xml:
* gobject/tut_tools.xml:
Format XML to be more editable. Describe Interfaces better. Add a
footnote at first occurance of 'maman_'.

svn path=/trunk/; revision=5334
This commit is contained in:
Stefan Kost 2007-02-10 22:08:42 +00:00
parent bdca945da3
commit 8ec7d6ca3f
7 changed files with 2209 additions and 2193 deletions

View File

@ -1,3 +1,14 @@
2007-02-11 Stefan Kost <ensonic@users.sf.net>
* gobject/tut_gobject.xml:
* gobject/tut_gsignal.xml:
* gobject/tut_gtype.xml:
* gobject/tut_howto.xml:
* gobject/tut_intro.xml:
* gobject/tut_tools.xml:
Format XML to be more editable. Describe Interfaces better. Add a
footnote at first occurance of 'maman_'.
2007-02-08 Stefan Kost <ensonic@users.sf.net>
* gobject/tut_gobject.xml:

View File

@ -1,64 +1,63 @@
<?xml version='1.0' encoding="ISO-8859-1"?>
<chapter id="chapter-gobject">
<title>The GObject base class</title>
<chapter id="chapter-gobject">
<title>The GObject base class</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><link linkend="GObject">GObject</link></type>.
</para>
<para>
<type><link linkend="GObject">GObject</link></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 GNOME libraries which use the GLib type system (like Gtk+ and GStreamer)
inherit from <type><link linkend="GObject">GObject</link></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 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><link linkend="GObject">GObject</link></type>.
</para>
<para>
<type><link linkend="GObject">GObject</link></type> is a fundamental classed instantiable type. It implements:
The <function><link linkend="g-object-new">g_object_new</link></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
and instance structures have 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>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>
<listitem><para>
Allocate and clear memory through <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>,
</para></listitem>
<listitem><para>
Initialize the object' instance with the construction properties.
</para></listitem>
</itemizedlist>
All the GNOME libraries which use the GLib type system (like Gtk+ and GStreamer)
inherit from <type><link linkend="GObject">GObject</link></type> which is why it is important to understand
the details of how it works.
Although one can expect all class and instance members (except the fields
pointing to the parents) to be set to zero, some consider it good practice to explicitly set them.
</para>
<sect1 id="gobject-instanciation">
<title>Object instanciation</title>
<para>
The <function><link linkend="g-object-new">g_object_new</link></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
and instance structures have 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 and clear memory through <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>,
</para></listitem>
<listitem><para>
Initialize the object' instance with the construction properties.
</para></listitem>
</itemizedlist>
Although one can expect all class and instance members (except the fields
pointing to the parents) to be set to zero, some consider it good practice to explicitly set them.
</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:
<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>
<para>
The example below shows how <type>MamanBar</type> overrides the parent's constructor:
<para>
The example below shows how <type>MamanBar</type> overrides the parent's constructor:
<programlisting>
#define MAMAN_TYPE_BAR (maman_bar_get_type ())
#define MAMAN_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_TYPE_BAR, MamanBar))
#define MAMAN_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MAMAN_TYPE_BAR, MamanBarClass))
#define MAMAN_IS_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_TYPE_BAR))
#define MAMAN_TYPE_BAR (maman_bar_get_type ())
#define MAMAN_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_TYPE_BAR, MamanBar))
#define MAMAN_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MAMAN_TYPE_BAR, MamanBarClass))
#define MAMAN_IS_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_TYPE_BAR))
#define MAMAN_IS_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MAMAN_TYPE_BAR))
#define MAMAN_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MAMAN_TYPE_BAR, MamanBarClass))
@ -142,153 +141,153 @@ GType maman_bar_get_type (void)
return type;
}
</programlisting>
If the user instantiates an object <type>MamanBar</type> with:
If the user instantiates an object <type>MamanBar</type> with:
<programlisting>
MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, 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>
</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><link linkend="g-object-new">g_object_new</link></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><link linkend="g-type-class-peek">g_type_class_peek</link></function> and <function><link linkend="g-type-class-peek-parent">g_type_class_peek_parent</link></function> functions.
</para>
<para>
Once <function><link linkend="g-object-new">g_object_new</link></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><link linkend="g-type-class-peek">g_type_class_peek</link></function> and <function><link linkend="g-type-class-peek-parent">g_type_class_peek_parent</link></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><link linkend="g-type-create-instance">g_type_create_instance</link></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><link linkend="g-type-create-instance">g_type_create_instance</link></function>
returns, <function>g_object_constructor</function> sets the construction properties
(ie: the properties which were given to <function><link linkend="g-object-new">g_object_new</link></function>) and returns
to the user's constructor which is then allowed to do useful instance initialization...
</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><link linkend="g-type-create-instance">g_type_create_instance</link></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><link linkend="g-type-create-instance">g_type_create_instance</link></function>
returns, <function>g_object_constructor</function> sets the construction properties
(ie: the properties which were given to <function><link linkend="g-object-new">g_object_new</link></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><link linkend="g-object-new">g_object_new</link></function> and their order of
invocation.
</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><link linkend="g-object-new">g_object_new</link></function> and their order of
invocation.
</para>
<para>
The array below lists the functions invoked by <function><link linkend="g-object-new">g_object_new</link></function> and
their order of invocation:
<para>
The array below lists the functions invoked by <function><link linkend="g-object-new">g_object_new</link></function> and
their order of invocation:
<table id="gobject-construction-table">
<title><function><link linkend="g-object-new">g_object_new</link></function></title>
<tgroup cols="3">
<colspec colwidth="*" colnum="1" align="left"/>
<colspec colwidth="*" colnum="2" align="left"/>
<colspec colwidth="8*" colnum="3" align="left"/>
<table id="gobject-construction-table">
<title><function><link linkend="g-object-new">g_object_new</link></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 morerows="3">First call to <function><link linkend="g-object-new">g_object_new</link></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><link linkend="g-object-new">g_object_new</link></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><link linkend="g-object-new">g_object_new</link></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><link linkend="g-object-new">g_object_new</link></function> for target type</entry-->
<entry>interface' interface_init function</entry>
<entry>On interface' vtable</entry>
<entry></entry>
</row>
<row>
<entry morerows="1">Each call to <function><link linkend="g-object-new">g_object_new</link></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><link linkend="g-object-new">g_object_new</link></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>
<thead>
<row>
<entry>Invocation time</entry>
<entry>Function Invoked</entry>
<entry>Function's parameters</entry>
<entry>Remark</entry>
</row>
</thead>
<tbody>
<row>
<entry morerows="3">First call to <function><link linkend="g-object-new">g_object_new</link></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><link linkend="g-object-new">g_object_new</link></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><link linkend="g-object-new">g_object_new</link></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><link linkend="g-object-new">g_object_new</link></function> for target type</entry-->
<entry>interface' interface_init function</entry>
<entry>On interface' vtable</entry>
<entry></entry>
</row>
<row>
<entry morerows="1">Each call to <function><link linkend="g-object-new">g_object_new</link></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><link linkend="g-object-new">g_object_new</link></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><link linkend="g-type-create-instance">g_type_create_instance</link></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>
<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><link linkend="g-type-create-instance">g_type_create_instance</link></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>
<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...). The methods which are used to
manipulate this reference count are described below.
<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...). The methods which are used to
manipulate this reference count are described below.
<programlisting>
/*
Refcounting
@ -299,14 +298,14 @@ 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);
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,
@ -314,205 +313,205 @@ void g_object_remove_weak_pointer (GObject *object,
/*
Cycle handling
*/
void g_object_run_dispose (GObject *object);
void g_object_run_dispose (GObject *object);
</programlisting>
</para>
</para>
<sect2 id="gobject-memory-refcount">
<title>Reference count</title>
<para>
The functions <function><link linkend="g-object-ref">g_object_ref</link></function>/<function><link linkend="g-object-unref">g_object_unref</link></function> respectively
increase and decrease the reference count.These functions are thread-safe as of GLib 2.8.
The reference count is, unsurprisingly, initialized to one by
<function><link linkend="g-object-new">g_object_new</link></function> which means that the caller
is currenly the sole owner of the newly-created reference.
When the reference count reaches zero, that is,
when <function><link linkend="g-object-unref">g_object_unref</link></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><link linkend="g-type-free-instance">g_type_free_instance</link></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"/> and
<xref linkend="gtype-non-instantiable-classed"/>.
</para>
<para>
The table below summarizes the destruction process of a GObject:
<table id="gobject-destruction-table">
<title><function><link linkend="g-object-unref">g_object_unref</link></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 morerows="1">Last call to <function><link linkend="g-object-unref">g_object_unref</link></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><link linkend="g-object-unref">g_object_unref</link></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"/>.
</entry>
</row>
<row>
<entry morerows="3">Last call to <function><link linkend="g-object-unref">g_object_unref</link></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><link linkend="g-object-unref">g_object_unref</link></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><link linkend="g-object-unref">g_object_unref</link></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><link linkend="g-object-unref">g_object_unref</link></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><link linkend="g-object-weak-ref">g_object_weak_ref</link></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>
<sect2 id="gobject-memory-refcount">
<title>Reference count</title>
<para>
<function><link linkend="g-object-weak-unref">g_object_weak_unref</link></function> can be used to remove a monitoring
callback from the object.
The functions <function><link linkend="g-object-ref">g_object_ref</link></function>/<function><link linkend="g-object-unref">g_object_unref</link></function> respectively
increase and decrease the reference count.These functions are thread-safe as of GLib 2.8.
The reference count is, unsurprisingly, initialized to one by
<function><link linkend="g-object-new">g_object_new</link></function> which means that the caller
is currenly the sole owner of the newly-created reference.
When the reference count reaches zero, that is,
when <function><link linkend="g-object-unref">g_object_unref</link></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><link linkend="g-type-free-instance">g_type_free_instance</link></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"/> and
<xref linkend="gtype-non-instantiable-classed"/>.
</para>
<para>
Weak References are also used to implement <function><link linkend="g-object-add-weak-pointer">g_object_add_weak_pointer</link></function>
and <function><link linkend="g-object-remove-weak-pointer">g_object_remove_weak_pointer</link></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.
The table below summarizes the destruction process of a GObject:
<table id="gobject-destruction-table">
<title><function><link linkend="g-object-unref">g_object_unref</link></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 morerows="1">Last call to <function><link linkend="g-object-unref">g_object_unref</link></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><link linkend="g-object-unref">g_object_unref</link></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"/>.
</entry>
</row>
<row>
<entry morerows="3">Last call to <function><link linkend="g-object-unref">g_object_unref</link></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><link linkend="g-object-unref">g_object_unref</link></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><link linkend="g-object-unref">g_object_unref</link></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><link linkend="g-object-unref">g_object_unref</link></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><link linkend="g-object-weak-ref">g_object_weak_ref</link></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><link linkend="g-object-weak-unref">g_object_weak_unref</link></function> can be used to remove a monitoring
callback from the object.
</para>
<para>
Weak References are also used to implement <function><link linkend="g-object-add-weak-pointer">g_object_add_weak_pointer</link></function>
and <function><link linkend="g-object-remove-weak-pointer">g_object_remove_weak_pointer</link></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.
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.
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><link linkend="g-object-dispose">g_object_dispose</link></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.
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><link linkend="g-object-dispose">g_object_dispose</link></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><link linkend="g-object-dispose">g_object_dispose</link></function> on one of the
objects.
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><link linkend="g-object-dispose">g_object_dispose</link></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 !
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 handled 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.
The above example, which might seem a bit contrived can really happen if your
GObject's are being handled 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>
<sect1 id="gobject-properties">
<title>Object properties</title>
<para>
One of GObject's nice features is its generic get/set mechanism for object
properties. When an object
@ -520,7 +519,7 @@ void g_object_run_dispose (GObject *object);
the object's properties with <function><link linkend="g-object-class-install-property">g_object_class_install_property</link></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:
@ -541,7 +540,6 @@ maman_bar_instance_init (GTypeInstance *instance,
MamanBar *self = (MamanBar *)instance;
}
static void
maman_bar_set_property (GObject *object,
guint property_id,
@ -638,7 +636,7 @@ g_object_set_property (G_OBJECT (bar), "papa-number", &amp;val);
</programlisting>
The client code just above looks simple but a lot of things happen under the hood:
</para>
<para>
<function><link linkend="g-object-set-property">g_object_set_property</link></function> first ensures a property
with this name was registered in bar's class_init handler. If so, it calls
@ -647,7 +645,7 @@ g_object_set_property (G_OBJECT (bar), "papa-number", &amp;val);
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,
@ -661,7 +659,7 @@ g_object_set_property (G_OBJECT (bar), "papa-number", &amp;val);
</footnote>
which matches and conversion will be caried out if needed.
</para>
<para>
After transformation, the <type><link linkend="GValue">GValue</link></type> is validated by
<function><link linkend="g-param-value-validate">g_param_value_validate</link></function> which makes sure the user's
@ -673,7 +671,7 @@ g_object_set_property (G_OBJECT (bar), "papa-number", &amp;val);
respect these constraints (it is set to 11, while the maximum is 10). As such, the
<function><link linkend="g-object-set-property">g_object_set_property</link></function> function will return with an error.
</para>
<para>
If the user's GValue had been set to a valid value, <function><link linkend="g-object-set-property">g_object_set_property</link></function>
would have proceeded with calling the object's set_property class method. Here, since our
@ -681,18 +679,18 @@ g_object_set_property (G_OBJECT (bar), "papa-number", &amp;val);
<function>foo_set_property</function> after having retrieved from the
<type><link linkend="GParamSpec">GParamSpec</link></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><link linkend="GParamSpec">GParamSpec</link></type> within the <type><link linkend="FooClass">FooClass</link></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>
<para>
It should be noted that the param_id used here need only to uniquely identify each
<type><link linkend="GParamSpec">GParamSpec</link></type> within the <type><link linkend="FooClass">FooClass</link></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><link linkend="g-object-class-install-property">g_object_class_install_property</link></function>.
</para>
<para>
Once the property has been set by the object's set_property class method, the code path
returns to <function><link linkend="g-object-set-property">g_object_set_property</link></function> which calls
@ -700,7 +698,7 @@ g_object_set_property (G_OBJECT (bar), "papa-number", &amp;val);
the "notify" signal is emitted on the object's instance with the changed property as
parameter unless notifications were frozen by <function><link linkend="g-object-freeze-notify">g_object_freeze_notify</link></function>.
</para>
<para>
<function><link linkend="g-object-thaw-notify">g_object_thaw_notify</link></function> can be used to re-enable notification of
property modifications through the "notify" signal. It is important to remember that
@ -719,13 +717,12 @@ g_object_set_property (G_OBJECT (bar), "papa-number", &amp;val);
</para>
<sect2 id="gobject-multi-properties">
<title>Accessing multiple properties at once</title>
<para>
It is interesting to note that the <function><link linkend="g-object-set">g_object_set</link></function> and
<function><link linkend="g-object-set-valist">g_object_set_valist</link></function> (vararg version) functions can be used to set
multiple properties at once. The client code shown above can then be re-written as:
<title>Accessing multiple properties at once</title>
<para>
It is interesting to note that the <function><link linkend="g-object-set">g_object_set</link></function> and
<function><link linkend="g-object-set-valist">g_object_set_valist</link></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 = /* */;
@ -734,41 +731,40 @@ g_object_set (G_OBJECT (foo),
"maman-name", "test",
NULL);
</programlisting>
This saves us from managing the GValues that we were needing to handle when using
<function><link linkend="g-object-set-property">g_object_set_property</link></function>.
The code above will trigger one notify signal emission for each property modified.
</para>
<para>
Of course, the _get versions are also available: <function><link linkend="g-object-get">g_object_get</link></function>
and <function><link linkend="g-object-get-valist">g_object_get_valist</link></function> (vararg version) can be used to get numerous
properties at once.
</para>
This saves us from managing the GValues that we were needing to handle when using
<function><link linkend="g-object-set-property">g_object_set_property</link></function>.
The code above will trigger one notify signal emission for each property modified.
</para>
<para>
Of course, the _get versions are also available: <function><link linkend="g-object-get">g_object_get</link></function>
and <function><link linkend="g-object-get-valist">g_object_get_valist</link></function> (vararg version) can be used to get numerous
properties at once.
</para>
<para>
These high level functions have one drawback - they don't provide a return result.
One should pay attention to the argument types and ranges when using them.
A know source of errors is to e.g. pass a gfloat instead of a gdouble and thus
shifting all subsequent parameters by four bytes. Also forgetting the terminating
NULL will lead to unexpected behaviour.
</para>
<para>
Really attentive readers now understand how <function><link linkend="g-object-new">g_object_new</link></function>,
<function><link linkend="g-object-newv">g_object_newv</link></function> and <function><link linkend="g-object-new-valist">g_object_new_valist</link></function>
work: they parse the user-provided variable number of parameters and invoke
<function><link linkend="g-object-set">g_object_set</link></function> on the parameters only after the object has been successfully constructed.
Of course, the "notify" signal will be emitted for each property set.
</para>
<para>
These high level functions have one drawback - they don't provide a return result.
One should pay attention to the argument types and ranges when using them.
A know source of errors is to e.g. pass a gfloat instead of a gdouble and thus
shifting all subsequent parameters by four bytes. Also forgetting the terminating
NULL will lead to unexpected behaviour.
</para>
<para>
Really attentive readers now understand how <function><link linkend="g-object-new">g_object_new</link></function>,
<function><link linkend="g-object-newv">g_object_newv</link></function> and <function><link linkend="g-object-new-valist">g_object_new_valist</link></function>
work: they parse the user-provided variable number of parameters and invoke
<function><link linkend="g-object-set">g_object_set</link></function> on the parameters only after the object has been successfully constructed.
Of course, the "notify" signal will be emitted for each property set.
</para>
</sect2>
<!-- @todo tell here about how to pass use handle properties in derived classe -->
</sect1>
</chapter>
</chapter>

View File

@ -1,83 +1,83 @@
<?xml version='1.0' encoding="ISO-8859-1"?>
<chapter id="chapter-signal">
<title>The GObject messaging system</title>
<chapter id="chapter-signal">
<title>The GObject messaging system</title>
<sect1 id="closure">
<title>Closures</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:
<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>
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>
<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><link linkend="GClosure">GClosure</link></type> structure represents the common functionality of all
closure implementations: there exists 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><link linkend="GCClosure">GCClosure</link></type> type which
is a specific implementation of closures to be used with C/C++ callbacks.
</para>
<para>
A <type><link linkend="GClosure">GClosure</link></type> provides simple services:
<itemizedlist>
<listitem><para>
Invocation (<function><link linkend="g-closure-invoke">g_closure_invoke</link></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><link linkend="g-closure-add-finalize-notifier">g_closure_add_finalize_notifier</link></function>
(finalization notification), <function><link linkend="g-closure-add-invalidate-notifier">g_closure_add_invalidate_notifier</link></function>
(invalidation notification) and
<function><link linkend="g-closure-add-marshal-guards">g_closure_add_marshal_guards</link></function> (invocation notification).
There exist symmetric de-registration functions for finalization and invalidation
events (<function><link linkend="g-closure-remove-finalize-notifier">g_closure_remove_finalize_notifier</link></function> and
<function><link linkend="g-closure-remove-invalidate-notifier">g_closure_remove_invalidate_notifier</link></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>
The <type><link linkend="GClosure">GClosure</link></type> structure represents the common functionality of all
closure implementations: there exists 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><link linkend="GCClosure">GCClosure</link></type> type which
is a specific implementation of closures to be used with C/C++ callbacks.
</para>
<para>
A <type><link linkend="GClosure">GClosure</link></type> provides simple services:
<itemizedlist>
<listitem><para>
Invocation (<function><link linkend="g-closure-invoke">g_closure_invoke</link></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><link linkend="g-closure-add-finalize-notifier">g_closure_add_finalize_notifier</link></function>
(finalization notification), <function><link linkend="g-closure-add-invalidate-notifier">g_closure_add_invalidate_notifier</link></function>
(invalidation notification) and
<function><link linkend="g-closure-add-marshal-guards">g_closure_add_marshal_guards</link></function> (invocation notification).
There exist symmetric de-registration functions for finalization and invalidation
events (<function><link linkend="g-closure-remove-finalize-notifier">g_closure_remove_finalize_notifier</link></function> and
<function><link linkend="g-closure-remove-invalidate-notifier">g_closure_remove_invalidate_notifier</link></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><link linkend="GCClosure">GCClosure</link></type>s
which have a pretty minimal API or the even simpler <function><link linkend="g-signal-connect">g_signal_connect</link></function>
functions (which will be presented a bit later :).
<programlisting>
If you are using C or C++
to connect a callback to a given event, you will either use the simple <type><link linkend="GCClosure">GCClosure</link></type>s
which have a pretty minimal API or the even simpler <function><link linkend="g-signal-connect">g_signal_connect</link></function>
functions (which will be presented a bit later :).
<programlisting>
GClosure* g_cclosure_new (GCallback callback_func,
gpointer user_data,
GClosureNotify destroy_data);
@ -86,46 +86,46 @@ GClosure* g_cclosure_new_swap (GCallback callback_func,
GClosureNotify destroy_data);
GClosure* g_signal_type_cclosure_new (GType itype,
guint struct_offset);
</programlisting>
</para>
</programlisting>
</para>
<para>
<function><link linkend="g-cclosure-new">g_cclosure_new</link></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><link linkend="g-cclosure-new">g_cclosure_new</link></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><link linkend="g-cclosure-new-swap">g_cclosure_new_swap</link></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><link linkend="g-cclosure-new">g_cclosure_new</link></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>
<para>
<function><link linkend="g-cclosure-new-swap">g_cclosure_new_swap</link></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><link linkend="g-cclosure-new">g_cclosure_new</link></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>
<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>
<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,
@ -151,57 +151,57 @@ g_cclosure_marshal_VOID__INT (GClosure *closure,
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 tuple which is the equivalent structure in python (you can
look in <function>pyg_closure_marshal</function> in <filename>pygtype.c</filename>
in the <emphasis>pygobject</emphasis> module in GNOME cvs server).
</para>
</sect2>
</sect1>
<sect1 id="signal">
<title>Signals</title>
</programlisting>
</para>
<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.
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 tuple which is the equivalent structure in python (you can
look in <function>pyg_closure_marshal</function> in <filename>pygtype.c</filename>
in the <emphasis>pygobject</emphasis> module in GNOME cvs server).
</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>
</sect2>
</sect1>
<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:
<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>
</para>
<sect2 id="signal-registration">
<title>Signal registration</title>
<sect2 id="signal-registration">
<title>Signal registration</title>
<para>
To register a new signal on an existing type, we can use any of <function><link linkend="g-signal-newv">g_signal_newv</link></function>,
<function><link linkend="g-signal-new-valist">g_signal_new_valist</link></function> or <function><link linkend="g-signal-new">g_signal_new</link></function> functions:
<para>
To register a new signal on an existing type, we can use any of <function><link linkend="g-signal-newv">g_signal_newv</link></function>,
<function><link linkend="g-signal-new-valist">g_signal_new_valist</link></function> or <function><link linkend="g-signal-new">g_signal_new</link></function> functions:
<programlisting>
guint g_signal_newv (const gchar *signal_name,
GType itype,
@ -214,307 +214,307 @@ guint g_signal_newv (const gchar *signal_name,
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>
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>
<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>
<sect2 id="signal-connection">
<title>Signal connection</title>
<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><link linkend="g-signal-override-class-closure">g_signal_override_class_closure</link></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><link linkend="g-signal-connect">g_signal_connect</link></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><link linkend="g-signal-add-emission-hook">g_signal_add_emission_hook</link></function>
and removed with <function><link linkend="g-signal-remove-emission-hook">g_signal_remove_emission_hook</link></function>.
</para>
<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><link linkend="g-signal-override-class-closure">g_signal_override_class_closure</link></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><link linkend="g-signal-connect">g_signal_connect</link></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><link linkend="g-signal-add-emission-hook">g_signal_add_emission_hook</link></function>
and removed with <function><link linkend="g-signal-remove-emission-hook">g_signal_remove_emission_hook</link></function>.
</para>
<para>
</para>
</sect2>
</sect2>
<sect2 id="signal-emission">
<title>Signal emission</title>
<sect2 id="signal-emission">
<title>Signal emission</title>
<para>
Signal emission is done through the use of the <function><link linkend="g-signal-emit">g_signal_emit</link></function> family
of functions.
<para>
Signal emission is done through the use of the <function><link linkend="g-signal-emit">g_signal_emit</link></function> family
of functions.
<programlisting>
void g_signal_emitv (const GValue *instance_and_params,
guint signal_id,
GQuark detail,
GValue *return_value);
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>
<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><link linkend="g-signal-connect">g_signal_connect</link></function> family of
functions, and if they are not blocked (with the <function><link linkend="g-signal-handler-block">g_signal_handler_block</link></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>
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><link linkend="g-signal-connect">g_signal_connect</link></function> family of
functions, and if they are not blocked (with the <function><link linkend="g-signal-handler-block">g_signal_handler_block</link></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><link linkend="g-signal-stop">g_signal_stop</link></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, at any point during emission (except in RUN_CLEANUP state), one of the
closures or emission hook stops the signal emission with
<function><link linkend="g-signal-stop">g_signal_stop</link></function>, 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><link linkend="g-signal-emit">g_signal_emit</link></function>.
</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><link linkend="g-signal-emit">g_signal_emit</link></function>.
</para>
</sect2>
</sect2>
<sect2 id="signal-detail">
<title>The <emphasis>detail</emphasis> argument</title>
<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>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><link linkend="GQuark">GQuark</link></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><link linkend="g-quark-from-string">g_quark_from_string</link></function> and <function><link linkend="g-quark-to-string">g_quark_to_string</link></function>.
</para>
</footnote>:
<para>
Of the three main connection functions,
only one has an explicit detail parameter as a <type><link linkend="GQuark">GQuark</link></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><link linkend="g-quark-from-string">g_quark_from_string</link></function> and <function><link linkend="g-quark-to-string">g_quark_to_string</link></function>.
</para>
</footnote>:
<programlisting>
gulong g_signal_connect_closure_by_id (gpointer instance,
guint signal_id,
GQuark detail,
GClosure *closure,
gboolean after);
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:
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);
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>
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><link linkend="GQuark">GQuark</link></type> again:
<para>
Of the four main signal emission functions, three have an explicit detail parameter as a
<type><link linkend="GQuark">GQuark</link></type> again:
<programlisting>
void g_signal_emitv (const GValue *instance_and_params,
guint signal_id,
GQuark detail,
GValue *return_value);
guint signal_id,
GQuark detail,
GValue *return_value);
void g_signal_emit_valist (gpointer instance,
guint signal_id,
GQuark detail,
va_list var_args);
guint signal_id,
GQuark detail,
va_list var_args);
void g_signal_emit (gpointer instance,
guint signal_id,
GQuark detail,
...);
guint signal_id,
GQuark detail,
...);
</programlisting>
The fourth function hides it in its signal name parameter:
The fourth function hides it in its signal name parameter:
<programlisting>
void g_signal_emit_by_name (gpointer instance,
const gchar *detailed_signal,
...);
const gchar *detailed_signal,
...);
</programlisting>
The format of the detailed_signal parameter is exactly the same as the format used by
the <function><link linkend="g-signal-connect">g_signal_connect</link></function> functions: <emphasis>signal_name::detail_name</emphasis>.
</para>
The format of the detailed_signal parameter is exactly the same as the format used by
the <function><link linkend="g-signal-connect">g_signal_connect</link></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.
If the closures' detail does not match the detail provided by the user, they will not be invoked
(even though they are connected to a signal which is being emitted).
</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.
If the closures' detail does not match the detail provided by the user, they will not be invoked
(even though they are connected to a signal which is being emitted).
</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>
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>
<para>
As a simple rule, users can and should set the detail parameter to zero: this will disable completely
this optional filtering.
</para>
</sect2>
</sect2>
</sect1>
</chapter>
</sect1>
</chapter>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,85 +1,90 @@
<chapter>
<title>Background</title>
<?xml version='1.0' encoding="ISO-8859-1"?>
<chapter id="chapter-intro">
<title>Background</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. describes briefly
the solution choosen by GLib.
</para>
<para>
The following chapters go into greater detail into how GType and GObject work and
how you can use them as a C programmer. It is useful to keep in mind that
allowing access to C objects from other interpreted languages was one of the major design
goals: this can often explain the sometimes rather convoluted APIs and features present
in this library.
</para>
<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. describes briefly
the solution choosen by GLib.
</para>
<para>The following chapters go into greater detail into how GType and GObject work and
how you can use them as a C programmer. It is useful to keep in mind that
allowing access to C objects from other interpreted languages was one of the major design
goals: this can often explain the sometimes rather convoluted APIs and features present
in this library.
</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:
<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>
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>
<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:
<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)
{}
@ -95,79 +100,80 @@ int main (int argc, char *argv[])
push $0xa
call 0x80482f4 &lt;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 calling 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 generic glue code which makes it possible to use
C objects written with GType directly in Python or Perl, with a minimum amount of work: there
is no need to generate huge amounts of glue code either automatically or by hand.
</para>
<para>Although that goal was arguably laudable, its pursuit has had a major influence on
the whole GType/GObject library. C programmers are likely to be puzzled at the complexity
of the features exposed in the following chapters if they forget that the GType/GObject library
was not only designed to offer OO-like features to C programmers but also transparent
cross-language interoperability.
</para>
</sect1>
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 calling 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 generic glue code which makes it possible to use
C objects written with GType directly in Python or Perl, with a minimum amount of work: there
is no need to generate huge amounts of glue code either automatically or by hand.
</para>
<para>
Although that goal was arguably laudable, its pursuit has had a major influence on
the whole GType/GObject library. C programmers are likely to be puzzled at the complexity
of the features exposed in the following chapters if they forget that the GType/GObject library
was not only designed to offer OO-like features to C programmers but also transparent
cross-language interoperability.
</para>
</sect1>
</chapter>

View File

@ -1,3 +1,4 @@
<?xml version='1.0' encoding="ISO-8859-1"?>
<partintro>
<para>
Several useful developer tools have been build around GObject technology.