mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-05-28 16:30:07 +02:00
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:
parent
bdca945da3
commit
8ec7d6ca3f
@ -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:
|
||||
|
@ -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", &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", &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", &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", &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", &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", &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", &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>
|
||||
|
||||
|
||||
|
||||
|
@ -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
@ -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 <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>
|
||||
|
@ -1,3 +1,4 @@
|
||||
<?xml version='1.0' encoding="ISO-8859-1"?>
|
||||
<partintro>
|
||||
<para>
|
||||
Several useful developer tools have been build around GObject technology.
|
||||
|
Loading…
x
Reference in New Issue
Block a user