docs: General cleanups and rewording in the GObject concepts docs

• Remove copies of function declarations from the explanation — if
   people want those, they can follow links to the reference manual.
 • Add markup to make C code more defined.
 • Remove use of first person and irrelevant name dropping.

https://bugzilla.gnome.org/show_bug.cgi?id=744060
This commit is contained in:
Philip Withnall 2015-02-23 15:30:57 +00:00
parent a86ef242e4
commit ab9b52e69c
4 changed files with 243 additions and 292 deletions

View File

@ -119,19 +119,21 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
order to find the parent class and chain up to the parent class order to find the parent class and chain up to the parent class
constructor, we can use the <literal>maman_bar_parent_class</literal> constructor, we can use the <literal>maman_bar_parent_class</literal>
pointer that has been set up for us by the pointer that has been set up for us by the
<literal>G_DEFINE_TYPE</literal> macro. <link linkend="G-DEFINE-TYPE:CAPS"><literal>G_DEFINE_TYPE</literal></link>
macro.
</para> </para>
<para> <para>
Finally, at one point or another, <function>g_object_constructor</function> is invoked 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 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> through <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>
which means that the <function>instance_init</function> function is invoked at this point if one which means that the <function>instance_init</function> function is invoked at this point if one
was registered. After <function>instance_init</function> returns, the object is fully initialized and should be was registered. After <function>instance_init</function> 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> ready to have its methods called by the user. When
<function><link linkend="g-type-create-instance">g_type_create_instance</link></function>
returns, <function>g_object_constructor</function> sets the construction properties returns, <function>g_object_constructor</function> sets the construction properties
(i.e. the properties which were given to <function><link linkend="g-object-new">g_object_new</link></function>) and returns (i.e. 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... to the user's constructor.
</para> </para>
<para> <para>
@ -163,10 +165,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
<entry>target type's <function>base_init</function> function</entry> <entry>target type's <function>base_init</function> function</entry>
<entry>On the inheritance tree of classes from fundamental type to target type. <entry>On the inheritance tree of classes from fundamental type to target type.
<function>base_init</function> is invoked once for each class structure.</entry> <function>base_init</function> is invoked once for each class structure.</entry>
<entry> <entry>Never used in practice. Unlikely you will need it.</entry>
I have no real idea on how this can be used. If you have a good real-life
example of how a class' <function>base_init</function> can be used, please, let me know.
</entry>
</row> </row>
<row> <row>
<!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry--> <!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry-->
@ -186,7 +185,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
</row> </row>
<row> <row>
<!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry--> <!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry-->
<entry>interface's interface_init function</entry> <entry>interface's <function>interface_init</function> function</entry>
<entry>On interface's vtable</entry> <entry>On interface's vtable</entry>
<entry></entry> <entry></entry>
</row> </row>
@ -327,7 +326,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
<entry morerows="3">Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last <entry morerows="3">Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last
instance of target type instance of target type
</entry> </entry>
<entry>interface's interface_finalize function</entry> <entry>interface's <function>interface_finalize</function> function</entry>
<entry>On interface's vtable</entry> <entry>On interface's vtable</entry>
<entry>Never used in practice. Unlikely you will need it.</entry> <entry>Never used in practice. Unlikely you will need it.</entry>
</row> </row>
@ -335,7 +334,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
<!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function>for the last <!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function>for the last
instance of target type instance of target type
</entry--> </entry-->
<entry>interface's base_finalize function</entry> <entry>interface's <function>base_finalize</function> function</entry>
<entry>On interface's vtable</entry> <entry>On interface's vtable</entry>
<entry>Never used in practice. Unlikely you will need it.</entry> <entry>Never used in practice. Unlikely you will need it.</entry>
</row> </row>
@ -343,7 +342,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
<!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last <!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last
instance of target type instance of target type
</entry--> </entry-->
<entry>target type's class_finalize function</entry> <entry>target type's <function>class_finalize</function> function</entry>
<entry>On target type's class structure</entry> <entry>On target type's class structure</entry>
<entry>Never used in practice. Unlikely you will need it.</entry> <entry>Never used in practice. Unlikely you will need it.</entry>
</row> </row>
@ -351,7 +350,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
<!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last <!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last
instance of target type instance of target type
</entry--> </entry-->
<entry>type's base_finalize function</entry> <entry>type's <function>base_finalize</function> function</entry>
<entry>On the inheritance tree of classes from fundamental type to target type. <entry>On the inheritance tree of classes from fundamental type to target type.
<function>base_init</function> is invoked once for each class structure.</entry> <function>base_init</function> is invoked once for each class structure.</entry>
<entry>Never used in practice. Unlikely you will need it.</entry> <entry>Never used in practice. Unlikely you will need it.</entry>
@ -367,7 +366,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
<title>Weak References</title> <title>Weak References</title>
<para> <para>
Weak References are used to monitor object finalization: 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 <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 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 its dispose method. As such, each weak ref can be invoked more than once upon
@ -381,12 +380,16 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
</para> </para>
<para> <para>
Weak References are also used to implement <function><link linkend="g-object-add-weak-pointer">g_object_add_weak_pointer</link></function> 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 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 to the object they are applied to which makes sure to nullify the pointer given by the user
when object is finalized. when object is finalized.
</para> </para>
<para>
Similarly, <link linkend="GWeakRef"><type>GWeakRef</type></link> can be
used to implement weak references if thread safety is required.
</para>
</sect2> </sect2>
<sect2 id="gobject-memory-cycles"> <sect2 id="gobject-memory-cycles">
@ -398,7 +401,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
the first phase, executed in the dispose handler is supposed to release all references 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 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 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. without program error in-between the two phases.
</para> </para>
<para> <para>
@ -410,8 +413,8 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
</para> </para>
<para> <para>
Attentive readers might now have understood one of the rules about the dispose handler This explains one of the rules about the dispose handler stated earlier:
we stated a bit sooner: the dispose handler can be invoked multiple times. Let's say we 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. 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 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-run-dispose">g_object_run_dispose</link></function> on one of the do this would be to invoke <function><link linkend="g-object-run-dispose">g_object_run_dispose</link></function> on one of the
@ -442,13 +445,12 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
One of GObject's nice features is its generic get/set mechanism for object One of GObject's nice features is its generic get/set mechanism for object
properties. When an object properties. When an object
is instantiated, the object's <function>class_init</function> handler should be used to register is instantiated, the object's <function>class_init</function> handler should be used to register
the object's properties with <function><link linkend="g-object-class-install-properties">g_object_class_install_properties</link></function> the object's properties with <function><link linkend="g-object-class-install-properties">g_object_class_install_properties</link></function>.
(implemented in <filename>gobject.c</filename>).
</para> </para>
<para> <para>
The best way to understand how object properties work is by looking at a real example The best way to understand how object properties work is by looking at a real example
on how it is used: of how it is used:
<informalexample><programlisting> <informalexample><programlisting>
/************************************************/ /************************************************/
/* Implementation */ /* Implementation */
@ -552,7 +554,7 @@ maman_bar_class_init (MamanBarClass *klass)
GObject *bar; GObject *bar;
GValue val = G_VALUE_INIT; GValue val = G_VALUE_INIT;
bar = g_object_new (MAMAN_TYPE_SUBBAR, NULL); bar = g_object_new (MAMAN_TYPE_BAR, NULL);
g_value_init (&amp;val, G_TYPE_CHAR); g_value_init (&amp;val, G_TYPE_CHAR);
g_value_set_char (&amp;val, 11); g_value_set_char (&amp;val, 11);
@ -567,14 +569,15 @@ g_value_unset (&amp;val);
<para> <para>
<function><link linkend="g-object-set-property">g_object_set_property</link></function> first ensures a property <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 <function>class_init</function> handler. If so it walks the class hierarchy, with this name was registered in bar's <function>class_init</function> handler. If so it walks the class hierarchy,
from bottom, most derived type, to top, fundamental type to find the class from bottom-most most-derived type, to top-most fundamental type to find the class
which registered that property. It then tries to convert the user-provided GValue which registered that property. It then tries to convert the user-provided
into a GValue whose type is that of the associated property. <link linkend="GValue"><type>GValue</type></link>
into a <type>GValue</type> whose type is that of the associated property.
</para> </para>
<para> <para>
If the user provides a signed char GValue, as is shown If the user provides a <type>signed char</type> <type>GValue</type>, as is shown
here, and if the object's property was registered as an unsigned int, here, and if the object's property was registered as an <type>unsigned int</type>,
<function><link linkend="g-value-transform">g_value_transform</link></function> will try to transform the input signed char into <function><link linkend="g-value-transform">g_value_transform</link></function> will try to transform the input signed char into
an unsigned int. Of course, the success of the transformation depends on the availability an unsigned int. Of course, the success of the transformation depends on the availability
of the required transform function. In practice, there will almost always be a transformation of the required transform function. In practice, there will almost always be a transformation
@ -601,8 +604,9 @@ g_value_unset (&amp;val);
<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> 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 would have proceeded with calling the object's
implementation of Foo did override this method, the code path would jump to <function>set_property</function> class method. Here, since our
implementation of <type>Foo</type> did override this method, execution would jump to
<function>foo_set_property</function> after having retrieved from the <function>foo_set_property</function> after having retrieved from the
<link linkend="GParamSpec"><type>GParamSpec</type></link> the <emphasis>param_id</emphasis> <link linkend="GParamSpec"><type>GParamSpec</type></link> the <emphasis>param_id</emphasis>
<footnote> <footnote>
@ -619,7 +623,8 @@ g_value_unset (&amp;val);
</para> </para>
<para> <para>
Once the property has been set by the object's set_property class method, the code path Once the property has been set by the object's
<function>set_property</function> class method, execution
returns to <function><link linkend="g-object-set-property">g_object_set_property</link></function> which makes sure that returns to <function><link linkend="g-object-set-property">g_object_set_property</link></function> which makes sure that
the "notify" signal is emitted on the object's instance with the changed property as 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>. parameter unless notifications were frozen by <function><link linkend="g-object-freeze-notify">g_object_freeze_notify</link></function>.
@ -627,11 +632,14 @@ g_value_unset (&amp;val);
<para> <para>
<function><link linkend="g-object-thaw-notify">g_object_thaw_notify</link></function> can be used to re-enable notification of <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 property modifications through the
<link linkend="GObject-notify"><type>“notify”</type></link> signal. It is important to remember that
even if properties are changed while property change notification is frozen, the "notify" even if properties are changed while property change notification is frozen, the "notify"
signal will be emitted once for each of these changed properties as soon as the property signal will be emitted once for each of these changed properties as soon as the property
change notification is thawed: no property change is lost for the "notify" signal. Signal change notification is thawed: no property change is lost for the "notify"
can only be delayed by the notification freezing mechanism. signal, although multiple notifications for a single property are
compressed. Signals can only be delayed by the notification freezing
mechanism.
</para> </para>
<para> <para>
@ -663,25 +671,28 @@ g_object_set (G_OBJECT (foo),
</para> </para>
<para> <para>
Of course, the _get versions are also available: <function><link linkend="g-object-get">g_object_get</link></function> Equivalent <function>_get</function> 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> (variadic version) can be used to get numerous and <function><link linkend="g-object-get-valist">g_object_get_valist</link></function> (variadic version) can be used to get numerous
properties at once. properties at once.
</para> </para>
<para> <para>
These high level functions have one drawback - they don't provide a return result. These high level functions have one drawback — they don't provide a return value.
One should pay attention to the argument types and ranges when using them. One should pay attention to the argument types and ranges when using them.
A known source of errors is to e.g. pass a gfloat instead of a gdouble and thus A known source of errors is to pass a different type from what the
shifting all subsequent parameters by four bytes. Also forgetting the terminating property expects; for instance, passing an integer when the property
NULL will lead to unexpected behaviour. expects a floating point value and thus shifting all subsequent parameters
by some number of bytes. Also forgetting the terminating
<literal>NULL</literal> will lead to undefined behaviour.
</para> </para>
<para> <para>
Really attentive readers now understand how <function><link linkend="g-object-new">g_object_new</link></function>, This explains 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> <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 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. <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. The "notify" signal will be emitted for each property set.
</para> </para>
</sect2> </sect2>

View File

@ -16,11 +16,11 @@
<itemizedlist> <itemizedlist>
<listitem><para>a function pointer (the callback itself) whose prototype looks like: <listitem><para>a function pointer (the callback itself) whose prototype looks like:
<informalexample><programlisting> <informalexample><programlisting>
return_type function_callback (... , gpointer user_data); return_type function_callback ( , gpointer user_data);
</programlisting></informalexample> </programlisting></informalexample>
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
the user_data pointer which is passed to the callback upon invocation of the closure the <parameter>user_data</parameter> pointer which is passed to the callback upon invocation of the closure
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
a function pointer which represents the destructor of the closure: whenever the a function pointer which represents the destructor of the closure: whenever the
@ -32,7 +32,7 @@ return_type function_callback (... , gpointer user_data);
<para> <para>
The <link linkend="GClosure"><type>GClosure</type></link> structure represents the common functionality of all The <link linkend="GClosure"><type>GClosure</type></link> structure represents the common functionality of all
closure implementations: there exists a different Closure implementation for closure implementations: there exists a different closure implementation for
each separate runtime which wants to use the GObject type system. each separate runtime which wants to use the GObject type system.
<footnote><para> <footnote><para>
In practice, closures sit at the boundary of language runtimes: if you are In practice, closures sit at the boundary of language runtimes: if you are
@ -79,32 +79,27 @@ return_type function_callback (... , gpointer user_data);
If you are using C or C++ If you are using C or C++
to connect a callback to a given event, you will either use simple <link linkend="GCClosure"><type>GCClosure</type></link>s to connect a callback to a given event, you will either use simple <link linkend="GCClosure"><type>GCClosure</type></link>s
which have a pretty minimal API or the even simpler <function><link linkend="g-signal-connect">g_signal_connect</link></function> 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 :). functions (which will be presented a bit later).
<informalexample><programlisting>
GClosure *g_cclosure_new (GCallback callback_func,
gpointer user_data,
GClosureNotify destroy_data);
GClosure *g_cclosure_new_swap (GCallback callback_func,
gpointer user_data,
GClosureNotify destroy_data);
GClosure *g_signal_type_cclosure_new (GType itype,
guint struct_offset);
</programlisting></informalexample>
</para> </para>
<para> <para>
<function><link linkend="g-cclosure-new">g_cclosure_new</link></function> will create a new closure which can invoke the <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 user-provided callback_func with the user-provided
is finalized (second stage of the destruction process), it will invoke the destroy_data function <parameter>user_data</parameter> as its last parameter. When the closure
if the user has supplied one. is finalized (second stage of the destruction process), it will invoke
the <parameter>destroy_data</parameter> function if the user has
supplied one.
</para> </para>
<para> <para>
<function><link linkend="g-cclosure-new-swap">g_cclosure_new_swap</link></function> will create a new closure which can invoke the <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 user-provided <parameter>callback_func</parameter> with the
user-provided <parameter>user_data</parameter> as its first parameter
(instead of being the
last parameter as with <function><link linkend="g-cclosure-new">g_cclosure_new</link></function>). When the closure 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 is finalized (second stage of the destruction process), it will invoke
function if the user has supplied one. the <parameter>destroy_data</parameter> function if the user has
supplied one.
</para> </para>
</sect2> </sect2>
@ -126,8 +121,17 @@ GClosure *g_signal_type_cclosure_new (GType itype,
</para> </para>
<para> <para>
The following code implements a simple marshaller in C for a C function which takes an A generic C closure marshaller is available as
integer as first parameter and returns void. <link linkend="g-cclosure-marshal-generic"><function>g_cclosure_marshal_generic</function></link>
which implements marshalling for all function types using libffi. Custom
marshallers for different types are not needed.
</para>
<para>
An example of a custom marshaller is given below, illustrating how
<type>GValue</type>s can be converted to a C function call. The
marshaller is for a C function which takes an integer as its first
parameter and returns void.
<informalexample><programlisting> <informalexample><programlisting>
g_cclosure_marshal_VOID__INT (GClosure *closure, g_cclosure_marshal_VOID__INT (GClosure *closure,
GValue *return_value, GValue *return_value,
@ -158,13 +162,11 @@ g_cclosure_marshal_VOID__INT (GClosure *closure,
</para> </para>
<para> <para>
Of course, there exist other kinds of marshallers. For example, James Henstridge There exist other kinds of marshallers, for example there is a generic
wrote a generic Python marshaller which is used by all Python closures (a Python closure 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). is used to invoke a callback written in Python). This Python marshaller
This Python marshaller transforms the input GValue list representing the function transforms the input GValue list representing the function parameters
parameters into a Python tuple which is the equivalent structure in Python (you can into a Python tuple which is the equivalent structure in Python.
look in <function>pyg_closure_marshal</function> in <filename>pygtype.c</filename>
in the <emphasis>pygobject</emphasis> module in the GNOME source code repository).
</para> </para>
</sect2> </sect2>
@ -177,8 +179,8 @@ g_cclosure_marshal_VOID__INT (GClosure *closure,
GObject's signals have nothing to do with standard UNIX signals: they connect GObject's signals have nothing to do with standard UNIX signals: they connect
arbitrary application-specific events with any number of listeners. arbitrary application-specific events with any number of listeners.
For example, in GTK+, every user event (keystroke or mouse move) is received 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 from the windowing system and generates a GTK+ event in the form of a signal emission
on a given object instance. on the widget object instance.
</para> </para>
<para> <para>
@ -195,7 +197,7 @@ g_cclosure_marshal_VOID__INT (GClosure *closure,
connected to this signal on this type instance will be invoked. 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: connected to such a signal represent callbacks whose signature looks like:
<informalexample><programlisting> <informalexample><programlisting>
return_type function_callback (gpointer instance, ... , gpointer user_data); return_type function_callback (gpointer instance, , gpointer user_data);
</programlisting></informalexample> </programlisting></informalexample>
</para> </para>
@ -221,43 +223,47 @@ guint g_signal_newv (const gchar *signal_name,
simple: simple:
<itemizedlist> <itemizedlist>
<listitem><para> <listitem><para>
signal_name: is a string which can be used to uniquely identify a given signal. <parameter>signal_name</parameter>: is a string which can be used to uniquely identify a given signal.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
itype: is the instance type on which this signal can be emitted. <parameter>itype</parameter>: is the instance type on which this signal can be emitted.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
signal_flags: partly defines the order in which closures which were connected to the <parameter>signal_flags</parameter>: partly defines the order in which closures which were connected to the
signal are invoked. signal are invoked.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
class_closure: this is the default closure for the signal: if it is not NULL upon <parameter>class_closure</parameter>: 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 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 moment where this closure is invoked compared to other closures connected to that
signal depends partly on the signal_flags. signal depends partly on the signal_flags.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
accumulator: this is a function pointer which is invoked after each closure <parameter>accumulator</parameter>: 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 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 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. value of the signal based on the return value of all the invoked closures.
For example, an accumulator could ignore
<literal>NULL</literal> returns from closures; or it
could build a list of the values returned by the
closures.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
accumulator_data: this pointer will be passed down to each invocation of the <parameter>accumulator_data</parameter>: this pointer will be passed down to each invocation of the
accumulator during emission. accumulator during emission.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
c_marshaller: this is the default C marshaller for any closure which is connected to <parameter>c_marshaller</parameter>: this is the default C marshaller for any closure which is connected to
this signal. this signal.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
return_type: this is the type of the return value of the signal. <parameter>return_type</parameter>: this is the type of the return value of the signal.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
n_params: this is the number of parameters this signal takes. <parameter>n_params</parameter>: this is the number of parameters this signal takes.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
param_types: this is an array of GTypes which indicate the type of each parameter <parameter>param_types</parameter>: 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. of the signal. The length of this array is indicated by n_params.
</para></listitem> </para></listitem>
</itemizedlist> </itemizedlist>
@ -279,12 +285,12 @@ guint g_signal_newv (const gchar *signal_name,
<itemizedlist> <itemizedlist>
<listitem><para> <listitem><para>
You can register a class closure at signal registration: this is a 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 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. of a given signal on <emphasis>any</emphasis> of the instances of the type which supports that signal.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
You can use <function><link linkend="g-signal-override-class-closure">g_signal_override_class_closure</link></function> which 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 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. only on a derived type of the type on which the signal was registered.
This function is of use only to language bindings. This function is of use only to language bindings.
</para></listitem> </para></listitem>
@ -318,101 +324,90 @@ void g_signal_emitv (const GValue *instance_and_params,
</programlisting></informalexample> </programlisting></informalexample>
<itemizedlist> <itemizedlist>
<listitem><para> <listitem><para>
The instance_and_params array of GValues contains the list of input The <parameter>instance_and_params</parameter> array of GValues contains the list of input
parameters to the signal. The first element of the array is the parameters to the signal. The first element of the array is the
instance pointer on which to invoke the signal. The following elements of instance pointer on which to invoke the signal. The following elements of
the array contain the list of parameters to the signal. the array contain the list of parameters to the signal.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
signal_id identifies the signal to invoke. <parameter>signal_id</parameter> identifies the signal to invoke.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
detail identifies the specific detail of the signal to invoke. A detail is a kind of <parameter>detail</parameter> 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 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 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 cases, you can safely set this value to zero. See <xref linkend="signal-detail"/> for
more details about this parameter. more details about this parameter.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
return_value holds the return value of the last closure invoked during emission if <parameter>return_value</parameter> holds the return value of the last closure invoked during emission if
no accumulator was specified. If an accumulator was specified during signal creation, 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 this accumulator is used to calculate the return value as a function of the return
values of all the closures invoked during emission. 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 If no closure is invoked during
emission, the return_value is nonetheless initialized to zero/null. emission, the <parameter>return_value</parameter> is nonetheless initialized to zero/null.
</para></listitem> </para></listitem>
</itemizedlist> </itemizedlist>
</para> </para>
<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: Signal emission can be decomposed in 5 steps:
<itemizedlist> <orderedlist>
<listitem><para> <listitem><para>
<emphasis>RUN_FIRST</emphasis>: if the G_SIGNAL_RUN_FIRST flag was used <literal>RUN_FIRST</literal>: if the
during signal registration and if there exist a class_closure for this signal, <link linkend="G-SIGNAL-RUN-FIRST:CAPS"><literal>G_SIGNAL_RUN_FIRST</literal></link> flag was used
the class_closure is invoked. Jump to <emphasis>EMISSION_HOOK</emphasis> state. during signal registration and if there exists a class closure for this signal,
the class closure is invoked.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
<emphasis>EMISSION_HOOK</emphasis>: if any emission hook was added to <literal>EMISSION_HOOK</literal>: if any emission hook was added to
the signal, they are invoked from first to last added. Accumulate return values the signal, they are invoked from first to last added. Accumulate return values.
and jump to <emphasis>HANDLER_RUN_FIRST</emphasis> state.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
<emphasis>HANDLER_RUN_FIRST</emphasis>: if any closure were connected <literal>HANDLER_RUN_FIRST</literal>: if any closure were connected
with the <function><link linkend="g-signal-connect">g_signal_connect</link></function> family of 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> 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. family of functions) they are run here, from first to last connected.
Jump to <emphasis>RUN_LAST</emphasis> state.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
<emphasis>RUN_LAST</emphasis>: if the G_SIGNAL_RUN_LAST <literal>RUN_LAST</literal>: if the <literal>G_SIGNAL_RUN_LAST</literal>
flag was set during registration and if a class_closure flag was set during registration and if a class closure
was set, it is invoked here. Jump to was set, it is invoked here.
<emphasis>HANDLER_RUN_LAST</emphasis> state.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
<emphasis>HANDLER_RUN_LAST</emphasis>: if any closure were connected <literal>HANDLER_RUN_LAST</literal>: if any closure were connected
with the <function>g_signal_connect_after</function> family of with the <function>g_signal_connect_after</function> family of
functions, if they were not invoked during HANDLER_RUN_FIRST and if they functions, if they were not invoked during <literal>HANDLER_RUN_FIRST</literal> and if they
are not blocked, they are run here, from first to last connected. are not blocked, they are run here, from first to last connected.
Jump to <emphasis>RUN_CLEANUP</emphasis> state.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
<emphasis>RUN_CLEANUP</emphasis>: if the G_SIGNAL_RUN_CLEANUP flag <literal>RUN_CLEANUP</literal>: if the <literal>G_SIGNAL_RUN_CLEANUP</literal> flag
was set during registration and if a class_closure was set, was set during registration and if a class closure was set,
it is invoked here. Signal emission is completed here. it is invoked here. Signal emission is completed here.
</para></listitem> </para></listitem>
</itemizedlist> </orderedlist>
</para> </para>
<para> <para>
If, at any point during emission (except in RUN_CLEANUP state), one of the If, at any point during emission (except in <literal>RUN_CLEANUP</literal> state), one of the
closures or emission hook stops the signal emission with closures or emission hook stops the signal emission with
<function><link linkend="g-signal-stop-emission">g_signal_stop_emission</link></function>, <function><link linkend="g-signal-stop-emission">g_signal_stop_emission</link></function>,
emission jumps to CLEANUP state. emission jumps to <literal>RUN_CLEANUP</literal> state.
</para> </para>
<para> <para>
If, at any point during emission, one of the closures or emission hook 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 emits the same signal on the same instance, emission is restarted from
the RUN_FIRST state. the <literal>RUN_FIRST</literal> state.
</para> </para>
<para> <para>
The accumulator function is invoked in all states, after invocation The accumulator function is invoked in all states, after invocation
of each closure (except in EMISSION_HOOK and CLEANUP). It accumulates of each closure (except in <literal>RUN_EMISSION_HOOK</literal> and
<literal>RUN_CLEANUP</literal>). It accumulates
the closure return value into the signal return value and returns TRUE or 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. FALSE. If, at any point, it does not return TRUE, emission jumps
to <literal>RUN_CLEANUP</literal> state.
</para> </para>
<para> <para>
@ -428,85 +423,60 @@ void g_signal_emitv (const GValue *instance_and_params,
<para>All the functions related to signal emission or signal connection have a parameter <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 named the <emphasis>detail</emphasis>. Sometimes, this parameter is hidden by the API
but it is always there, under one form or another. but it is always there, in one form or another.
</para> </para>
<para> <para>
Of the three main connection functions, Of the three main connection functions,
only one has an explicit detail parameter as a <link linkend="GQuark"><type>GQuark</type></link> only one has an explicit detail parameter as a <link linkend="GQuark"><type>GQuark</type></link>:
<link linkend="g-signal-connect-closure-by-id"><function>g_signal_connect_closure_by_id</function></link>.
<footnote> <footnote>
<para>A GQuark is an integer which uniquely represents a string. It is possible to transform <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 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>. <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> </para>
</footnote>: </footnote>
<informalexample><programlisting> </para>
gulong g_signal_connect_closure_by_id (gpointer instance, <para>
guint signal_id, The two other functions,
GQuark detail, <link linkend="g-signal-connect-closure"><function>g_signal_connect_closure</function></link> and
GClosure *closure, <link linkend="g-signal-connect-data"><function>g_signal_connect_data</function></link>
gboolean after); hide the detail parameter in the signal name identification.
</programlisting></informalexample> Their <parameter>detailed_signal</parameter> parameter is a
The two other functions hide the detail parameter in the signal name identification: string which identifies the name of the signal to connect to.
<informalexample><programlisting> The format of this string should match
gulong g_signal_connect_closure (gpointer instance, <emphasis>signal_name::detail_name</emphasis>. For example,
const gchar *detailed_signal, connecting to the signal named
GClosure *closure, <emphasis>notify::cursor_position</emphasis> will actually
gboolean after); connect to the signal named <emphasis>notify</emphasis> with the
gulong g_signal_connect_data (gpointer instance, <emphasis>cursor_position</emphasis> detail.
const gchar *detailed_signal,
GCallback c_handler,
gpointer data,
GClosureNotify destroy_data,
GConnectFlags connect_flags);
</programlisting></informalexample>
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. Internally, the detail string is transformed to a GQuark if it is present.
</para> </para>
<para> <para>
Of the four main signal emission functions, three have an explicit detail parameter as a Of the four main signal emission functions, one hides it in its
signal name parameter:
<link linkend="g-signal-connect"><function>g_signal_connect</function></link>.
The other three have an explicit detail parameter as a
<link linkend="GQuark"><type>GQuark</type></link> again: <link linkend="GQuark"><type>GQuark</type></link> again:
<informalexample><programlisting> <link linkend="g-signal-emit"><function>g_signal_emit</function></link>,
void g_signal_emitv (const GValue *instance_and_params, <link linkend="g-signal-emitv"><function>g_signal_emitv</function></link> and
guint signal_id, <link linkend="g-signal-emit-valist"><function>g_signal_emit_valist</function></link>.
GQuark detail,
GValue *return_value);
void g_signal_emit_valist (gpointer instance,
guint signal_id,
GQuark detail,
va_list var_args);
void g_signal_emit (gpointer instance,
guint signal_id,
GQuark detail,
...);
</programlisting></informalexample>
The fourth function hides it in its signal name parameter:
<informalexample><programlisting>
void g_signal_emit_by_name (gpointer instance,
const gchar *detailed_signal,
...);
</programlisting></informalexample>
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>
<para> <para>
If a detail is provided by the user to the emission function, it is used during emission to match 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. 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 If a closure's detail does not match the detail provided by the user, it
(even though they are connected to a signal which is being emitted). will not be invoked (even though it is connected to a signal which is
being emitted).
</para> </para>
<para> <para>
This completely optional filtering mechanism is mainly used as an optimization for signals 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 which are often emitted for many different reasons: the clients can filter out which events they are
interested in before the closure's marshalling code runs. For example, this is used extensively interested in 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, by the <link linkend="GObject-notify"><structfield>notify</structfield></link> 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 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 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. to only one property to filter most events before receiving them.
@ -514,7 +484,7 @@ void g_signal_emit_by_name (gpointer instance,
<para> <para>
As a simple rule, users can and should set the detail parameter to zero: this will disable completely As a simple rule, users can and should set the detail parameter to zero: this will disable completely
this optional filtering. this optional filtering for that signal.
</para> </para>
</sect2> </sect2>

View File

@ -45,23 +45,16 @@ GType g_type_register_fundamental (GType type_id,
</para> </para>
<para> <para>
<function><link linkend="g-type-register-static">g_type_register_static</link></function> and <function><link linkend="g-type-register-static">g_type_register_static</link></function>,
<function><link linkend="g-type-register-dynamic">g_type_register_dynamic</link></function> and
<function><link linkend="g-type-register-fundamental">g_type_register_fundamental</link></function> <function><link linkend="g-type-register-fundamental">g_type_register_fundamental</link></function>
are the C functions, defined in are the C functions, defined in
<filename>gtype.h</filename> and implemented in <filename>gtype.c</filename> <filename>gtype.h</filename> and implemented in <filename>gtype.c</filename>
which you should use to register a new <link linkend="GType"><type>GType</type></link> in the program's type system. which you should use to register a new <link linkend="GType"><type>GType</type></link> in the program's type system.
It is not likely you will ever need to use It is not likely you will ever need to use
<function><link linkend="g-type-register-fundamental">g_type_register_fundamental</link></function> (you have to be Tim Janik <function><link linkend="g-type-register-fundamental">g_type_register_fundamental</link></function>
to do that) but in case you want to, the last chapter explains how to create but in case you want to, the last chapter explains how to create
new fundamental types. new fundamental types.
<footnote>
<para>
Please note that there exists another registration function: the
<function><link linkend="g-type-register-dynamic">g_type_register_dynamic</link></function>. We will not discuss this
function here since its use is very similar to the <function>_static</function>
version.
</para>
</footnote>
</para> </para>
<para> <para>
@ -80,8 +73,8 @@ GType g_type_register_fundamental (GType type_id,
class size: the class_size field in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>. class size: the class_size field in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
class initialization functions (C++ constructor): the base_init and class initialization functions (C++ constructor): the <function>base_init</function> and
class_init fields in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>. <function>class_init</function> fields in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
class destruction functions (C++ destructor): the base_finalize and class destruction functions (C++ destructor): the base_finalize and
@ -131,8 +124,7 @@ GType g_type_register_fundamental (GType type_id,
<para> <para>
The following code shows how you can copy around a 64 bit integer, as well as a <link linkend="GObject"><type>GObject</type></link> The following code shows how you can copy around a 64 bit integer, as well as a <link linkend="GObject"><type>GObject</type></link>
instance pointer (sample code for this is located in the source tarball for this document in instance pointer:
<filename>sample/gtype/test.c</filename>):
<informalexample><programlisting> <informalexample><programlisting>
static void test_int (void) static void test_int (void)
{ {
@ -140,7 +132,7 @@ static void test_int (void)
GValue b_value = G_VALUE_INIT; GValue b_value = G_VALUE_INIT;
guint64 a, b; guint64 a, b;
a = 0xdeadbeaf; a = 0xdeadbeef;
g_value_init (&amp;a_value, G_TYPE_UINT64); g_value_init (&amp;a_value, G_TYPE_UINT64);
g_value_set_uint64 (&amp;a_value, a); g_value_set_uint64 (&amp;a_value, a);
@ -170,9 +162,9 @@ static void test_object (void)
g_value_init (&amp;obj_valb, G_TYPE_OBJECT); g_value_init (&amp;obj_valb, G_TYPE_OBJECT);
/* g_value_copy's semantics for G_TYPE_OBJECT types is to copy the reference. /* g_value_copy's semantics for G_TYPE_OBJECT types is to copy the reference.
This function thus calls g_object_ref. * This function thus calls g_object_ref.
It is interesting to note that the assignment works here because * It is interesting to note that the assignment works here because
MAMAN_TYPE_BAR is a G_TYPE_OBJECT. * MAMAN_TYPE_BAR is a G_TYPE_OBJECT.
*/ */
g_value_copy (&amp;obj_vala, &amp;obj_valb); g_value_copy (&amp;obj_vala, &amp;obj_valb);
@ -188,39 +180,15 @@ static void test_object (void)
</para> </para>
<para> <para>
The value_table used to specify these assignment functions is defined in The value table used to specify these assignment functions is
<filename>gtype.h</filename> and is thoroughly described in the documented in
API documentation provided with GObject (for once ;-) which is why we will <link linkend="GTypeValueTable"><type>GTypeValueTable</type></link>.
not detail its exact semantics. </para>
<informalexample><programlisting> <para>
typedef struct _GTypeValueTable GTypeValueTable;
struct _GTypeValueTable
{
void (*value_init) (GValue *value);
void (*value_free) (GValue *value);
void (*value_copy) (const GValue *src_value,
GValue *dest_value);
/* varargs functionality (optional) */
gpointer (*value_peek_pointer) (const GValue *value);
gchar *collect_format;
gchar* (*collect_value) (GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags);
gchar *lcopy_format;
gchar* (*lcopy_value) (const GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags);
};
</programlisting></informalexample>
Interestingly, it is also very unlikely Interestingly, it is also very unlikely
you will ever need to specify a value_table during type registration you will ever need to specify a value_table during type registration
because these value_tables are inherited from the parent types for because these value_tables are inherited from the parent types for
non-fundamental types which means that unless you want to write a non-fundamental types.
fundamental type (not a great idea!), you will not need to provide
a new value_table since you will inherit the value_table structure
from your parent type.
</para> </para>
</sect1> </sect1>
@ -246,7 +214,7 @@ struct _GTypeValueTable
<footnote> <footnote>
<para> <para>
<emphasis>Maman</emphasis> is the French word for <emphasis>mum</emphasis> <emphasis>Maman</emphasis> is the French word for <emphasis>mum</emphasis>
or <emphasis>mother</emphasis> - nothing more and nothing less. or <emphasis>mother</emphasis> nothing more and nothing less.
</para> </para>
</footnote> </footnote>
@ -342,8 +310,7 @@ G_DEFINE_TYPE (MamanBar, maman_bar, G_TYPE_OBJECT)
<para> <para>
A lot of types are not instantiable by the type system and do not have A lot of types are not instantiable by the type system and do not have
a class. Most of these types are fundamental trivial types such as <emphasis>gchar</emphasis>, a class. Most of these types are fundamental trivial types such as <emphasis>gchar</emphasis>,
and are already registered in <function>_g_value_types_init</function> and are already registered by GLib.
(in <filename>gvaluetypes.c</filename>).
</para> </para>
<para> <para>
@ -412,7 +379,8 @@ G_DEFINE_TYPE (MamanBar, maman_bar, G_TYPE_OBJECT)
<para> <para>
For example, the code below shows how you could register For example, the code below shows how you could register
such a fundamental object type in the type system: such a fundamental object type in the type system (using none of the
GObject convenience API):
<informalexample><programlisting> <informalexample><programlisting>
typedef struct { typedef struct {
GObject parent; GObject parent;
@ -509,7 +477,8 @@ typedef struct {
The C standard mandates that the first field of a C structure is stored starting The C standard mandates that the first field of a C structure is stored starting
in the first byte of the buffer used to hold the structure's fields in memory. in the first byte of the buffer used to hold the structure's fields in memory.
This means that the first field of an instance of an object B is A's first field This means that the first field of an instance of an object B is A's first field
which in turn is GTypeInstance's first field which in turn is g_class, a pointer which in turn is <type>GTypeInstance</type>'s first field which in
turn is <structfield>g_class</structfield>, a pointer
to B's class structure. to B's class structure.
</para> </para>
@ -532,14 +501,11 @@ B *b;
<para> <para>
instantiation of these types can be done with instantiation of these types can be done with
<function><link linkend="g-type-create-instance">g_type_create_instance</link></function>: <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>,
<informalexample><programlisting> which will look up the type information
GTypeInstance* g_type_create_instance (GType type); structure associated with the type requested. Then, the instance size and instantiation
void g_type_free_instance (GTypeInstance *instance); policy (if the <structfield>n_preallocs</structfield> field is set
</programlisting></informalexample> to a non-zero value, the type system allocates
<function><link linkend="g-type-create-instance">g_type_create_instance</link></function> will look up the type information
structure associated to the type requested. Then, the instance size and instantiation
policy (if the n_preallocs field is set to a non-zero value, the type system allocates
the object's instance structures in chunks rather than mallocing for every instance) the object's instance structures in chunks rather than mallocing for every instance)
declared by the user are used to get a buffer to hold the object's instance declared by the user are used to get a buffer to hold the object's instance
structure. structure.
@ -551,8 +517,9 @@ void g_type_free_instance (GTypeInstance *instance);
class structure (ie: the embedded parent class structure) is initialized by copying the contents from class structure (ie: the embedded parent class structure) is initialized by copying the contents from
the class structure of the parent class. The rest of class structure is initialized to zero. If there the class structure of the parent class. The rest of class structure is initialized to zero. If there
is no parent, the entire class structure is initialized to zero. The type system then invokes the is no parent, the entire class structure is initialized to zero. The type system then invokes the
base_class_initialization functions (<link linkend="GBaseInitFunc"><type>GBaseInitFunc</type></link>) from topmost <function>base_class_initialization</function> functions
fundamental object to bottom-most most derived object. The object's class_init (<link linkend="GBaseInitFunc"><type>GBaseInitFunc</type></link>) from topmost
fundamental object to bottom-most most derived object. The object's <function>class_init</function>
(<link linkend="GClassInitFunc"><type>GClassInitFunc</type></link>) function is invoked afterwards to complete (<link linkend="GClassInitFunc"><type>GClassInitFunc</type></link>) function is invoked afterwards to complete
initialization of the class structure. initialization of the class structure.
Finally, the object's interfaces are initialized (we will discuss interface initialization Finally, the object's interfaces are initialized (we will discuss interface initialization
@ -562,8 +529,10 @@ void g_type_free_instance (GTypeInstance *instance);
<para> <para>
Once the type system has a pointer to an initialized class structure, it sets the object's Once the type system has a pointer to an initialized class structure, it sets the object's
instance class pointer to the object's class structure and invokes the object's instance class pointer to the object's class structure and invokes the object's
instance_init (<link linkend="GInstanceInitFunc"><type>GInstanceInitFunc</type></link>)functions, from top-most fundamental <function>instance_init</function>
type to bottom-most most derived type. (<link linkend="GInstanceInitFunc"><type>GInstanceInitFunc</type></link>)
functions, from top-most fundamental
type to bottom-most most-derived type.
</para> </para>
<para> <para>
@ -585,15 +554,15 @@ void g_type_free_instance (GTypeInstance *instance);
</para> </para>
<para> <para>
As many readers have now understood it, the base initialization/finalization process is The base initialization/finalization process is
very similar to the C++ constructor/destructor paradigm. The practical details are different very similar to the C++ constructor/destructor paradigm. The practical details are different
though and it is important not to get confused by superficial similarities. though and it is important not to get confused by superficial similarities.
GTypes have no instance destruction mechanism. It is GTypes have no instance destruction mechanism. It is
the user's responsibility to implement correct destruction semantics on top the user's responsibility to implement correct destruction semantics on top
of the existing GType code. (this is what GObject does. See of the existing GType code. (This is what GObject does: see
<xref linkend="chapter-gobject"/>) <xref linkend="chapter-gobject"/>.)
Furthermore, C++ code equivalent to the base_init Furthermore, C++ code equivalent to the <function>base_init</function>
and class_init callbacks of GType is usually not needed because C++ cannot really create object and <function>class_init</function> callbacks of GType is usually not needed because C++ cannot really create object
types at runtime. types at runtime.
</para> </para>
@ -609,20 +578,20 @@ void g_type_free_instance (GTypeInstance *instance);
<thead> <thead>
<row> <row>
<entry>Invocation time</entry> <entry>Invocation time</entry>
<entry>Function Invoked</entry> <entry>Function invoked</entry>
<entry>Function's parameters</entry> <entry>Function's parameters</entry>
</row> </row>
</thead> </thead>
<tbody> <tbody>
<row> <row>
<entry morerows="2">First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry> <entry morerows="2">First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry>
<entry>type's base_init function</entry> <entry>type's <function>base_init</function> function</entry>
<entry>On the inheritance tree of classes from fundamental type to target type. <entry>On the inheritance tree of classes from fundamental type to target type.
base_init is invoked once for each class structure.</entry> <function>base_init</function> is invoked once for each class structure.</entry>
</row> </row>
<row> <row>
<!--entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry--> <!--entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry-->
<entry>target type's class_init function</entry> <entry>target type's <function>class_init</function> function</entry>
<entry>On target type's class structure</entry> <entry>On target type's class structure</entry>
</row> </row>
<row> <row>
@ -633,7 +602,7 @@ void g_type_free_instance (GTypeInstance *instance);
</row> </row>
<row> <row>
<entry>Each call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry> <entry>Each call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry>
<entry>target type's instance_init function</entry> <entry>target type's <function>instance_init</function> function</entry>
<entry>On object's instance</entry> <entry>On object's instance</entry>
</row> </row>
<row> <row>
@ -644,14 +613,14 @@ void g_type_free_instance (GTypeInstance *instance);
</row> </row>
<row> <row>
<!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for target type</entry--> <!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for target type</entry-->
<entry>target type's class_finalize function</entry> <entry>target type's <function>class_finalize</function> function</entry>
<entry>On target type's class structure</entry> <entry>On target type's class structure</entry>
</row> </row>
<row> <row>
<!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for target type</entry--> <!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for target type</entry-->
<entry>type's base_finalize function</entry> <entry>type's <function>base_finalize</function> function</entry>
<entry>On the inheritance tree of classes from fundamental type to target type. <entry>On the inheritance tree of classes from fundamental type to target type.
base_finalize is invoked once for each class structure.</entry> <function>base_finalize</function> is invoked once for each class structure.</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
@ -674,7 +643,7 @@ void g_type_free_instance (GTypeInstance *instance);
<para> <para>
GType's interfaces are very similar to Java's interfaces. They allow GType's interfaces are very similar to Java's interfaces. They allow
to describe a common API that several classes will adhere to. to describe a common API that several classes will adhere to.
Imagine the play, pause and stop buttons on hi-fi equipment - those can Imagine the play, pause and stop buttons on hi-fi equipment those can
be seen as a playback interface. Once you know what they do, you can be seen as a playback interface. Once you know what they do, you can
control your CD player, MP3 player or anything that uses these symbols. control your CD player, MP3 player or anything that uses these symbols.
To declare an interface you have to register a non-instantiable To declare an interface you have to register a non-instantiable
@ -708,8 +677,8 @@ void maman_ibaz_do_action (MamanIbaz *self)
} }
</programlisting></informalexample> </programlisting></informalexample>
<function>maman_ibaz_get_type</function> registers a type named <emphasis>MamanIbaz</emphasis> <function>maman_ibaz_get_type</function> registers a type named <emphasis>MamanIbaz</emphasis>
which inherits from G_TYPE_INTERFACE. All interfaces must be children of G_TYPE_INTERFACE in the which inherits from <type>G_TYPE_INTERFACE</type>. All interfaces must
inheritance tree. be children of <type>G_TYPE_INTERFACE</type> in the inheritance tree.
</para> </para>
<para> <para>
@ -717,7 +686,7 @@ void maman_ibaz_do_action (MamanIbaz *self)
a <link linkend="GTypeInterface"><type>GTypeInterface</type></link> structure. The interface structure is expected to a <link linkend="GTypeInterface"><type>GTypeInterface</type></link> structure. The interface structure is expected to
contain the function pointers of the interface methods. It is good style to contain the function pointers of the interface methods. It is good style to
define helper functions for each of the interface methods which simply call define helper functions for each of the interface methods which simply call
the interface' method directly: <function>maman_ibaz_do_action</function> the interface's method directly: <function>maman_ibaz_do_action</function>
is one of these. is one of these.
</para> </para>
@ -829,10 +798,13 @@ G_DEFINE_TYPE_WITH_CODE (MamanBaz, maman_baz, G_TYPE_OBJECT,
First a memory buffer is allocated to hold the interface structure. The parent's First a memory buffer is allocated to hold the interface structure. The parent's
interface structure is then copied over to the new interface structure (the parent interface structure is then copied over to the new interface structure (the parent
interface is already initialized at that point). If there is no parent interface, interface is already initialized at that point). If there is no parent interface,
the interface structure is initialized with zeros. The g_type and the g_instance_type the interface structure is initialized with zeros. The
fields are then initialized: g_type is set to the type of the most-derived interface <structfield>g_type</structfield> and the
and g_instance_type is set to the type of the most derived type which implements <structfield>g_instance_type</structfield> fields are then
this interface. initialized: <structfield>g_type</structfield> is set to the type of
the most-derived interface and
<structfield>g_instance_type</structfield> is set to the type of the
most derived type which implements this interface.
</para> </para>
<para> <para>
@ -900,9 +872,7 @@ maman_ibaz_default_init (MamanIbazInterface *iface)
</para> </para>
<para> <para>
If you have found the stuff about interface hairy, you are right: it is hairy but In summary, interface initialization uses the following functions:
there is not much I can do about it. What I can do is summarize what you need to know
about interfaces:
</para> </para>
<para> <para>
@ -953,9 +923,6 @@ maman_ibaz_default_init (MamanIbazInterface *iface)
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
It is highly unlikely (i.e. I do not know of <emphasis>anyone</emphasis> who actually
used it) you will ever need other more fancy things such as the ones described in the
following section (<xref linkend="gtype-non-instantiable-classed-dest"/>).
</para> </para>
</sect2> </sect2>
@ -1007,15 +974,15 @@ maman_ibaz_default_init (MamanIbazInterface *iface)
<entry morerows="1">Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for type <entry morerows="1">Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for type
implementing interface implementing interface
</entry> </entry>
<entry>interface' interface_finalize function</entry> <entry>interface's <function>interface_finalize</function> function</entry>
<entry>On interface' vtable</entry> <entry>On interface's vtable</entry>
</row> </row>
<row> <row>
<!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function>for type <!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function>for type
implementing interface implementing interface
</entry--> </entry-->
<entry>interface' base_finalize function</entry> <entry>interface's <function>base_finalize</function> function</entry>
<entry>On interface' vtable</entry> <entry>On interface's vtable</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>

View File

@ -34,7 +34,7 @@
<title>Data types and programming</title> <title>Data types and programming</title>
<para> <para>
One could say (I have seen such definitions used in some textbooks on programming language theory) One could say
that a programming language is merely a way to create data types and manipulate them. Most languages 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 provide a number of language-native types and a few primitives to create more complex types based
on these primitive types. on these primitive types.
@ -44,7 +44,7 @@
In C, the language provides types such as <emphasis>char</emphasis>, <emphasis>long</emphasis>, 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 <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 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 (assuming one exists), 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 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). runtime, during the program execution (or just before execution if it uses a Just In Time compiler engine).
</para> </para>
@ -87,14 +87,17 @@ print "this is an integer converted to a string:" . $tmp . "\n";
<para> <para>
For the sake of discussion, here is a sample C function and the associated 32 bit x86 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: assembly code generated by GCC on a Linux computer:
<informalexample><programlisting> <informalexample><programlisting>
static void function_foo (int foo) static void
{} function_foo (int foo)
int main (int argc, char *argv[])
{ {
}
int
main (int argc,
char *argv[])
{
function_foo (10); function_foo (10);
return 0; return 0;
@ -106,7 +109,7 @@ call 0x80482f4 &lt;function_foo>
The assembly code shown above is pretty straightforward: the first instruction pushes 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 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 <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). GCC as native function calls (this is probably the fastest implementation possible).
</para> </para>
<para> <para>