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
constructor, we can use the <literal>maman_bar_parent_class</literal>
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>
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>
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
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
(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>
@ -163,10 +165,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
<entry>target type's <function>base_init</function> function</entry>
<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>
<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>
<entry>Never used in practice. Unlikely you will need it.</entry>
</row>
<row>
<!--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>
<!--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></entry>
</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
instance of target type
</entry>
<entry>interface's interface_finalize function</entry>
<entry>interface's <function>interface_finalize</function> function</entry>
<entry>On interface's vtable</entry>
<entry>Never used in practice. Unlikely you will need it.</entry>
</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
instance of target type
</entry-->
<entry>interface's base_finalize function</entry>
<entry>interface's <function>base_finalize</function> function</entry>
<entry>On interface's vtable</entry>
<entry>Never used in practice. Unlikely you will need it.</entry>
</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
instance of 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>Never used in practice. Unlikely you will need it.</entry>
</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
instance of 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.
<function>base_init</function> is invoked once for each class structure.</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>
<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
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
@ -381,12 +380,16 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
</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
to the object they are applied to which makes sure to nullify the pointer given by the user
when object is finalized.
</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 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
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.
without program error in-between the two phases.
</para>
<para>
@ -410,8 +413,8 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
</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
This explains one of the rules about the dispose handler stated earlier:
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-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
properties. When an object
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>
(implemented in <filename>gobject.c</filename>).
the object's properties with <function><link linkend="g-object-class-install-properties">g_object_class_install_properties</link></function>.
</para>
<para>
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>
/************************************************/
/* Implementation */
@ -552,7 +554,7 @@ maman_bar_class_init (MamanBarClass *klass)
GObject *bar;
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_set_char (&amp;val, 11);
@ -567,14 +569,15 @@ g_value_unset (&amp;val);
<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 <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
which registered that property. It then tries to convert the user-provided GValue
into a GValue whose type is that of the associated property.
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
<link linkend="GValue"><type>GValue</type></link>
into a <type>GValue</type> whose type is 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,
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 <type>unsigned int</type>,
<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
of the required transform function. In practice, there will almost always be a transformation
@ -601,8 +604,9 @@ g_value_unset (&amp;val);
<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
implementation of Foo did override this method, the code path would jump to
would have proceeded with calling the object's
<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
<link linkend="GParamSpec"><type>GParamSpec</type></link> the <emphasis>param_id</emphasis>
<footnote>
@ -619,7 +623,8 @@ g_value_unset (&amp;val);
</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
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>.
@ -627,11 +632,14 @@ g_value_unset (&amp;val);
<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
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"
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
can only be delayed by the notification freezing mechanism.
change notification is thawed: no property change is lost for the "notify"
signal, although multiple notifications for a single property are
compressed. Signals can only be delayed by the notification freezing
mechanism.
</para>
<para>
@ -663,25 +671,28 @@ g_object_set (G_OBJECT (foo),
</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
properties at once.
</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.
A known 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.
A known source of errors is to pass a different type from what the
property expects; for instance, passing an integer when the property
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>
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>
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.
The "notify" signal will be emitted for each property set.
</para>
</sect2>

View File

@ -16,11 +16,11 @@
<itemizedlist>
<listitem><para>a function pointer (the callback itself) whose prototype looks like:
<informalexample><programlisting>
return_type function_callback (... , gpointer user_data);
return_type function_callback ( , gpointer user_data);
</programlisting></informalexample>
</para></listitem>
<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>
<listitem><para>
a function pointer which represents the destructor of the closure: whenever the
@ -32,7 +32,7 @@ return_type function_callback (... , gpointer user_data);
<para>
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.
<footnote><para>
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++
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>
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>
functions (which will be presented a bit later).
</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.
user-provided callback_func with the user-provided
<parameter>user_data</parameter> as its last parameter. When the closure
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>
<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
is finalized (second stage of the destruction process), it will invoke the destroy_data
function 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>
</sect2>
@ -124,10 +119,19 @@ GClosure *g_signal_type_cclosure_new (GType itype,
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.
A generic C closure marshaller is available as
<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>
g_cclosure_marshal_VOID__INT (GClosure *closure,
GValue *return_value,
@ -158,13 +162,11 @@ g_cclosure_marshal_VOID__INT (GClosure *closure,
</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 the GNOME source code repository).
There exist other kinds of marshallers, for example there is a generic
Python marshaller which is used by all Python closures (a Python closure
is used to invoke a callback written in Python). This Python marshaller
transforms the input GValue list representing the function parameters
into a Python tuple which is the equivalent structure in Python.
</para>
</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
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.
from the windowing system and generates a GTK+ event in the form of a signal emission
on the widget object instance.
</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 such a signal represent callbacks whose signature looks like:
<informalexample><programlisting>
return_type function_callback (gpointer instance, ... , gpointer user_data);
return_type function_callback (gpointer instance, , gpointer user_data);
</programlisting></informalexample>
</para>
@ -221,43 +223,47 @@ guint g_signal_newv (const gchar *signal_name,
simple:
<itemizedlist>
<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>
<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>
<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.
</para></listitem>
<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
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
<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
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.
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>
<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.
</para></listitem>
<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.
</para></listitem>
<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>
<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>
<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.
</para></listitem>
</itemizedlist>
@ -279,12 +285,12 @@ guint g_signal_newv (const gchar *signal_name,
<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.
system-wide operation. i.e.: the class closure will be invoked during each emission
of a given signal on <emphasis>any</emphasis> of 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
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>
@ -318,101 +324,90 @@ void g_signal_emitv (const GValue *instance_and_params,
</programlisting></informalexample>
<itemizedlist>
<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
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.
<parameter>signal_id</parameter> 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
<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
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
<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,
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.
<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.
emission, the <parameter>return_value</parameter> 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>
<orderedlist>
<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.
<literal>RUN_FIRST</literal>: if the
<link linkend="G-SIGNAL-RUN-FIRST:CAPS"><literal>G_SIGNAL_RUN_FIRST</literal></link> flag was used
during signal registration and if there exists a class closure for this signal,
the class closure is invoked.
</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.
<literal>EMISSION_HOOK</literal>: if any emission hook was added to
the signal, they are invoked from first to last added. Accumulate return values.
</para></listitem>
<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
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.
<literal>RUN_LAST</literal>: if the <literal>G_SIGNAL_RUN_LAST</literal>
flag was set during registration and if a class closure
was set, it is invoked here.
</para></listitem>
<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
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.
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,
<literal>RUN_CLEANUP</literal>: if the <literal>G_SIGNAL_RUN_CLEANUP</literal> flag
was set during registration and if a class closure was set,
it is invoked here. Signal emission is completed here.
</para></listitem>
</itemizedlist>
</orderedlist>
</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
<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>
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.
the <literal>RUN_FIRST</literal> state.
</para>
<para>
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
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>
@ -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
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>
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>
<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>:
<informalexample><programlisting>
gulong g_signal_connect_closure_by_id (gpointer instance,
guint signal_id,
GQuark detail,
GClosure *closure,
gboolean after);
</programlisting></informalexample>
The two other functions hide the detail parameter in the signal name identification:
<informalexample><programlisting>
gulong g_signal_connect_closure (gpointer instance,
const gchar *detailed_signal,
GClosure *closure,
gboolean after);
gulong g_signal_connect_data (gpointer instance,
const gchar *detailed_signal,
GCallback c_handler,
gpointer data,
GClosureNotify destroy_data,
GConnectFlags connect_flags);
</programlisting></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.
</footnote>
</para>
<para>
The two other functions,
<link linkend="g-signal-connect-closure"><function>g_signal_connect_closure</function></link> and
<link linkend="g-signal-connect-data"><function>g_signal_connect_data</function></link>
hide the detail parameter in the signal name identification.
Their <parameter>detailed_signal</parameter> parameter is a
string which identifies the name of the signal to connect to.
The format of this string should match
<emphasis>signal_name::detail_name</emphasis>. For example,
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> detail.
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
<link linkend="GQuark"><type>GQuark</type></link> again:
<informalexample><programlisting>
void g_signal_emitv (const GValue *instance_and_params,
guint signal_id,
GQuark detail,
GValue *return_value);
void g_signal_emit_valist (gpointer instance,
guint signal_id,
GQuark detail,
va_list var_args);
void g_signal_emit (gpointer instance,
guint signal_id,
GQuark detail,
...);
</programlisting></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>.
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="g-signal-emit"><function>g_signal_emit</function></link>,
<link linkend="g-signal-emitv"><function>g_signal_emitv</function></link> and
<link linkend="g-signal-emit-valist"><function>g_signal_emit_valist</function></link>.
</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).
If a closure's detail does not match the detail provided by the user, it
will not be invoked (even though it is 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 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
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.
@ -514,7 +484,7 @@ void g_signal_emit_by_name (gpointer instance,
<para>
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>
</sect2>

View File

@ -45,23 +45,16 @@ GType g_type_register_fundamental (GType type_id,
</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>
are the C functions, defined in
<filename>gtype.h</filename> and implemented in <filename>gtype.c</filename>
which you should use to register a new <link linkend="GType"><type>GType</type></link> in the program's type system.
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
to do that) but in case you want to, the last chapter explains how to create
<function><link linkend="g-type-register-fundamental">g_type_register_fundamental</link></function>
but in case you want to, the last chapter explains how to create
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>
@ -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>.
</para></listitem>
<listitem><para>
class initialization functions (C++ constructor): the base_init and
class_init fields in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>.
class initialization functions (C++ constructor): the <function>base_init</function> and
<function>class_init</function> fields in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>.
</para></listitem>
<listitem><para>
class destruction functions (C++ destructor): the base_finalize and
@ -131,8 +124,7 @@ GType g_type_register_fundamental (GType type_id,
<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>
instance pointer (sample code for this is located in the source tarball for this document in
<filename>sample/gtype/test.c</filename>):
instance pointer:
<informalexample><programlisting>
static void test_int (void)
{
@ -140,7 +132,7 @@ static void test_int (void)
GValue b_value = G_VALUE_INIT;
guint64 a, b;
a = 0xdeadbeaf;
a = 0xdeadbeef;
g_value_init (&amp;a_value, G_TYPE_UINT64);
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_copy's semantics for G_TYPE_OBJECT types is to copy the reference.
This function thus calls g_object_ref.
It is interesting to note that the assignment works here because
MAMAN_TYPE_BAR is a G_TYPE_OBJECT.
* This function thus calls g_object_ref.
* It is interesting to note that the assignment works here because
* MAMAN_TYPE_BAR is a G_TYPE_OBJECT.
*/
g_value_copy (&amp;obj_vala, &amp;obj_valb);
@ -188,39 +180,15 @@ static void test_object (void)
</para>
<para>
The value_table used to specify these assignment functions is defined in
<filename>gtype.h</filename> and is thoroughly described in the
API documentation provided with GObject (for once ;-) which is why we will
not detail its exact semantics.
<informalexample><programlisting>
typedef struct _GTypeValueTable GTypeValueTable;
struct _GTypeValueTable
{
void (*value_init) (GValue *value);
void (*value_free) (GValue *value);
void (*value_copy) (const GValue *src_value,
GValue *dest_value);
/* varargs functionality (optional) */
gpointer (*value_peek_pointer) (const GValue *value);
gchar *collect_format;
gchar* (*collect_value) (GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags);
gchar *lcopy_format;
gchar* (*lcopy_value) (const GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags);
};
</programlisting></informalexample>
The value table used to specify these assignment functions is
documented in
<link linkend="GTypeValueTable"><type>GTypeValueTable</type></link>.
</para>
<para>
Interestingly, it is also very unlikely
you will ever need to specify a value_table during type registration
because these value_tables are inherited from the parent types for
non-fundamental types which means that unless you want to write a
fundamental type (not a great idea!), you will not need to provide
a new value_table since you will inherit the value_table structure
from your parent type.
non-fundamental types.
</para>
</sect1>
@ -246,7 +214,7 @@ struct _GTypeValueTable
<footnote>
<para>
<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>
</footnote>
@ -342,8 +310,7 @@ G_DEFINE_TYPE (MamanBar, maman_bar, G_TYPE_OBJECT)
<para>
A lot of types are not instantiable by the type system and do not have
a class. Most of these types are fundamental trivial types such as <emphasis>gchar</emphasis>,
and are already registered in <function>_g_value_types_init</function>
(in <filename>gvaluetypes.c</filename>).
and are already registered by GLib.
</para>
<para>
@ -412,7 +379,8 @@ G_DEFINE_TYPE (MamanBar, maman_bar, G_TYPE_OBJECT)
<para>
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>
typedef struct {
GObject parent;
@ -509,7 +477,8 @@ typedef struct {
The C standard mandates that the first field of a C structure is stored starting
in the first byte of the buffer used to hold the structure's fields in memory.
This means that the first field of an instance of an object B is A's first field
which in turn is GTypeInstance's first field which in turn is g_class, a pointer
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.
</para>
@ -523,7 +492,7 @@ b->parent.parent.g_class->g_type
or, more quickly:
<informalexample><programlisting>
B *b;
((GTypeInstance*)b)->g_class->g_type
((GTypeInstance *) b)->g_class->g_type
</programlisting></informalexample>
</para>
@ -532,14 +501,11 @@ B *b;
<para>
instantiation of these types can be done with
<function><link linkend="g-type-create-instance">g_type_create_instance</link></function>:
<informalexample><programlisting>
GTypeInstance* g_type_create_instance (GType type);
void g_type_free_instance (GTypeInstance *instance);
</programlisting></informalexample>
<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
<function><link linkend="g-type-create-instance">g_type_create_instance</link></function>,
which will look up the type information
structure associated with the type requested. Then, the instance size and instantiation
policy (if the <structfield>n_preallocs</structfield> field is set
to a non-zero value, the type system allocates
the object's instance structures in chunks rather than mallocing for every instance)
declared by the user are used to get a buffer to hold the object's instance
structure.
@ -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
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
base_class_initialization functions (<link linkend="GBaseInitFunc"><type>GBaseInitFunc</type></link>) from topmost
fundamental object to bottom-most most derived object. The object's class_init
<function>base_class_initialization</function> functions
(<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
initialization of the class structure.
Finally, the object's interfaces are initialized (we will discuss interface initialization
@ -562,8 +529,10 @@ void g_type_free_instance (GTypeInstance *instance);
<para>
Once the type system has a pointer to an initialized class structure, it sets the object's
instance class pointer to the object's class structure and invokes the object's
instance_init (<link linkend="GInstanceInitFunc"><type>GInstanceInitFunc</type></link>)functions, from top-most fundamental
type to bottom-most most derived type.
<function>instance_init</function>
(<link linkend="GInstanceInitFunc"><type>GInstanceInitFunc</type></link>)
functions, from top-most fundamental
type to bottom-most most-derived type.
</para>
<para>
@ -585,15 +554,15 @@ void g_type_free_instance (GTypeInstance *instance);
</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
though and it is important not to get confused by superficial similarities.
GTypes have no instance destruction mechanism. It is
the user's responsibility to implement correct destruction semantics on top
of the existing GType code. (this is what GObject does. See
<xref linkend="chapter-gobject"/>)
Furthermore, C++ code equivalent to the base_init
and class_init callbacks of GType is usually not needed because C++ cannot really create object
of the existing GType code. (This is what GObject does: see
<xref linkend="chapter-gobject"/>.)
Furthermore, C++ code equivalent to the <function>base_init</function>
and <function>class_init</function> callbacks of GType is usually not needed because C++ cannot really create object
types at runtime.
</para>
@ -609,20 +578,20 @@ void g_type_free_instance (GTypeInstance *instance);
<thead>
<row>
<entry>Invocation time</entry>
<entry>Function Invoked</entry>
<entry>Function invoked</entry>
<entry>Function's parameters</entry>
</row>
</thead>
<tbody>
<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>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.
base_init is invoked once for each class structure.</entry>
<function>base_init</function> is invoked once for each class structure.</entry>
</row>
<row>
<!--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>
</row>
<row>
@ -633,7 +602,7 @@ void g_type_free_instance (GTypeInstance *instance);
</row>
<row>
<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>
</row>
<row>
@ -644,14 +613,14 @@ void g_type_free_instance (GTypeInstance *instance);
</row>
<row>
<!--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>
</row>
<row>
<!--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.
base_finalize is invoked once for each class structure.</entry>
<function>base_finalize</function> is invoked once for each class structure.</entry>
</row>
</tbody>
</tgroup>
@ -674,7 +643,7 @@ void g_type_free_instance (GTypeInstance *instance);
<para>
GType's interfaces are very similar to Java's interfaces. They allow
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
control your CD player, MP3 player or anything that uses these symbols.
To declare an interface you have to register a non-instantiable
@ -708,8 +677,8 @@ void maman_ibaz_do_action (MamanIbaz *self)
}
</programlisting></informalexample>
<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
inheritance tree.
which inherits from <type>G_TYPE_INTERFACE</type>. All interfaces must
be children of <type>G_TYPE_INTERFACE</type> in the inheritance tree.
</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
contain the function pointers of the interface methods. It is good style to
define helper functions for each of the interface methods which simply call
the interface' method directly: <function>maman_ibaz_do_action</function>
the interface's method directly: <function>maman_ibaz_do_action</function>
is one of these.
</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
interface structure is then copied over to the new interface structure (the parent
interface is already initialized at that point). If there is no parent interface,
the interface structure is initialized with zeros. The g_type and the g_instance_type
fields are then initialized: g_type is set to the type of the most-derived interface
and g_instance_type is set to the type of the most derived type which implements
this interface.
the interface structure is initialized with zeros. The
<structfield>g_type</structfield> and the
<structfield>g_instance_type</structfield> fields are then
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>
@ -900,9 +872,7 @@ maman_ibaz_default_init (MamanIbazInterface *iface)
</para>
<para>
If you have found the stuff about interface hairy, you are right: it is hairy but
there is not much I can do about it. What I can do is summarize what you need to know
about interfaces:
In summary, interface initialization uses the following functions:
</para>
<para>
@ -953,9 +923,6 @@ maman_ibaz_default_init (MamanIbazInterface *iface)
</tbody>
</tgroup>
</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>
</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
implementing interface
</entry>
<entry>interface' interface_finalize function</entry>
<entry>On interface' vtable</entry>
<entry>interface's <function>interface_finalize</function> function</entry>
<entry>On interface's vtable</entry>
</row>
<row>
<!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function>for type
implementing interface
</entry-->
<entry>interface' base_finalize function</entry>
<entry>On interface' vtable</entry>
<entry>interface's <function>base_finalize</function> function</entry>
<entry>On interface's vtable</entry>
</row>
</tbody>
</tgroup>

View File

@ -34,7 +34,7 @@
<title>Data types and programming</title>
<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
provide a number of language-native types and a few primitives to create more complex types based
on these primitive types.
@ -44,7 +44,7 @@
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
(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
runtime, during the program execution (or just before execution if it uses a Just In Time compiler engine).
</para>
@ -87,17 +87,20 @@ print "this is an integer converted to a string:" . $tmp . "\n";
<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:
assembly code generated by GCC on a Linux computer:
<informalexample><programlisting>
static void function_foo (int foo)
{}
int main (int argc, char *argv[])
static void
function_foo (int foo)
{
}
function_foo (10);
int
main (int argc,
char *argv[])
{
function_foo (10);
return 0;
return 0;
}
push $0xa
@ -106,7 +109,7 @@ call 0x80482f4 &lt;function_foo>
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).
GCC as native function calls (this is probably the fastest implementation possible).
</para>
<para>