mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-24 14:36:13 +01:00
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:
parent
a86ef242e4
commit
ab9b52e69c
@ -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 (&val, G_TYPE_CHAR);
|
||||
g_value_set_char (&val, 11);
|
||||
@ -567,14 +569,15 @@ g_value_unset (&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 (&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 (&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 (&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>
|
||||
|
@ -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>
|
||||
|
@ -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 (&a_value, G_TYPE_UINT64);
|
||||
g_value_set_uint64 (&a_value, a);
|
||||
@ -170,9 +162,9 @@ static void test_object (void)
|
||||
g_value_init (&obj_valb, G_TYPE_OBJECT);
|
||||
|
||||
/* g_value_copy's semantics for G_TYPE_OBJECT types is to copy the reference.
|
||||
This function thus calls g_object_ref.
|
||||
It is interesting to note that the assignment works here because
|
||||
MAMAN_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 (&obj_vala, &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>
|
||||
|
@ -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 <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>
|
||||
|
Loading…
Reference in New Issue
Block a user