mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-05-02 12:06:53 +02: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
|
order to find the parent class and chain up to the parent class
|
||||||
constructor, we can use the <literal>maman_bar_parent_class</literal>
|
constructor, we can use the <literal>maman_bar_parent_class</literal>
|
||||||
pointer that has been set up for us by the
|
pointer that has been set up for us by the
|
||||||
<literal>G_DEFINE_TYPE</literal> macro.
|
<link linkend="G-DEFINE-TYPE:CAPS"><literal>G_DEFINE_TYPE</literal></link>
|
||||||
|
macro.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Finally, at one point or another, <function>g_object_constructor</function> is invoked
|
Finally, at one point or another, <function>g_object_constructor</function> is invoked
|
||||||
by the last constructor in the chain. This function allocates the object's instance' buffer
|
by the last constructor in the chain. This function allocates the object's instance buffer
|
||||||
through <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>
|
through <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>
|
||||||
which means that the <function>instance_init</function> function is invoked at this point if one
|
which means that the <function>instance_init</function> function is invoked at this point if one
|
||||||
was registered. After <function>instance_init</function> returns, the object is fully initialized and should be
|
was registered. After <function>instance_init</function> returns, the object is fully initialized and should be
|
||||||
ready to answer any user-request. When <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>
|
ready to have its methods called by the user. When
|
||||||
|
<function><link linkend="g-type-create-instance">g_type_create_instance</link></function>
|
||||||
returns, <function>g_object_constructor</function> sets the construction properties
|
returns, <function>g_object_constructor</function> sets the construction properties
|
||||||
(i.e. the properties which were given to <function><link linkend="g-object-new">g_object_new</link></function>) and returns
|
(i.e. the properties which were given to <function><link linkend="g-object-new">g_object_new</link></function>) and returns
|
||||||
to the user's constructor which is then allowed to do useful instance initialization...
|
to the user's constructor.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -163,10 +165,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
|
|||||||
<entry>target type's <function>base_init</function> function</entry>
|
<entry>target type's <function>base_init</function> function</entry>
|
||||||
<entry>On the inheritance tree of classes from fundamental type to target type.
|
<entry>On the inheritance tree of classes from fundamental type to target type.
|
||||||
<function>base_init</function> is invoked once for each class structure.</entry>
|
<function>base_init</function> is invoked once for each class structure.</entry>
|
||||||
<entry>
|
<entry>Never used in practice. Unlikely you will need it.</entry>
|
||||||
I have no real idea on how this can be used. If you have a good real-life
|
|
||||||
example of how a class' <function>base_init</function> can be used, please, let me know.
|
|
||||||
</entry>
|
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry-->
|
<!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry-->
|
||||||
@ -186,7 +185,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
|
|||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry-->
|
<!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry-->
|
||||||
<entry>interface's interface_init function</entry>
|
<entry>interface's <function>interface_init</function> function</entry>
|
||||||
<entry>On interface's vtable</entry>
|
<entry>On interface's vtable</entry>
|
||||||
<entry></entry>
|
<entry></entry>
|
||||||
</row>
|
</row>
|
||||||
@ -327,7 +326,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
|
|||||||
<entry morerows="3">Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last
|
<entry morerows="3">Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last
|
||||||
instance of target type
|
instance of target type
|
||||||
</entry>
|
</entry>
|
||||||
<entry>interface's interface_finalize function</entry>
|
<entry>interface's <function>interface_finalize</function> function</entry>
|
||||||
<entry>On interface's vtable</entry>
|
<entry>On interface's vtable</entry>
|
||||||
<entry>Never used in practice. Unlikely you will need it.</entry>
|
<entry>Never used in practice. Unlikely you will need it.</entry>
|
||||||
</row>
|
</row>
|
||||||
@ -335,7 +334,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
|
|||||||
<!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function>for the last
|
<!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function>for the last
|
||||||
instance of target type
|
instance of target type
|
||||||
</entry-->
|
</entry-->
|
||||||
<entry>interface's base_finalize function</entry>
|
<entry>interface's <function>base_finalize</function> function</entry>
|
||||||
<entry>On interface's vtable</entry>
|
<entry>On interface's vtable</entry>
|
||||||
<entry>Never used in practice. Unlikely you will need it.</entry>
|
<entry>Never used in practice. Unlikely you will need it.</entry>
|
||||||
</row>
|
</row>
|
||||||
@ -343,7 +342,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
|
|||||||
<!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last
|
<!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last
|
||||||
instance of target type
|
instance of target type
|
||||||
</entry-->
|
</entry-->
|
||||||
<entry>target type's class_finalize function</entry>
|
<entry>target type's <function>class_finalize</function> function</entry>
|
||||||
<entry>On target type's class structure</entry>
|
<entry>On target type's class structure</entry>
|
||||||
<entry>Never used in practice. Unlikely you will need it.</entry>
|
<entry>Never used in practice. Unlikely you will need it.</entry>
|
||||||
</row>
|
</row>
|
||||||
@ -351,7 +350,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
|
|||||||
<!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last
|
<!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last
|
||||||
instance of target type
|
instance of target type
|
||||||
</entry-->
|
</entry-->
|
||||||
<entry>type's base_finalize function</entry>
|
<entry>type's <function>base_finalize</function> function</entry>
|
||||||
<entry>On the inheritance tree of classes from fundamental type to target type.
|
<entry>On the inheritance tree of classes from fundamental type to target type.
|
||||||
<function>base_init</function> is invoked once for each class structure.</entry>
|
<function>base_init</function> is invoked once for each class structure.</entry>
|
||||||
<entry>Never used in practice. Unlikely you will need it.</entry>
|
<entry>Never used in practice. Unlikely you will need it.</entry>
|
||||||
@ -367,7 +366,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
|
|||||||
<title>Weak References</title>
|
<title>Weak References</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Weak References are used to monitor object finalization:
|
Weak references are used to monitor object finalization:
|
||||||
<function><link linkend="g-object-weak-ref">g_object_weak_ref</link></function> adds a monitoring callback which does
|
<function><link linkend="g-object-weak-ref">g_object_weak_ref</link></function> adds a monitoring callback which does
|
||||||
not hold a reference to the object but which is invoked when the object runs
|
not hold a reference to the object but which is invoked when the object runs
|
||||||
its dispose method. As such, each weak ref can be invoked more than once upon
|
its dispose method. As such, each weak ref can be invoked more than once upon
|
||||||
@ -381,12 +380,16 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Weak References are also used to implement <function><link linkend="g-object-add-weak-pointer">g_object_add_weak_pointer</link></function>
|
Weak references are also used to implement <function><link linkend="g-object-add-weak-pointer">g_object_add_weak_pointer</link></function>
|
||||||
and <function><link linkend="g-object-remove-weak-pointer">g_object_remove_weak_pointer</link></function>. These functions add a weak reference
|
and <function><link linkend="g-object-remove-weak-pointer">g_object_remove_weak_pointer</link></function>. These functions add a weak reference
|
||||||
to the object they are applied to which makes sure to nullify the pointer given by the user
|
to the object they are applied to which makes sure to nullify the pointer given by the user
|
||||||
when object is finalized.
|
when object is finalized.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Similarly, <link linkend="GWeakRef"><type>GWeakRef</type></link> can be
|
||||||
|
used to implement weak references if thread safety is required.
|
||||||
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="gobject-memory-cycles">
|
<sect2 id="gobject-memory-cycles">
|
||||||
@ -398,7 +401,7 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
|
|||||||
the first phase, executed in the dispose handler is supposed to release all references
|
the first phase, executed in the dispose handler is supposed to release all references
|
||||||
to other member objects. The second phase, executed by the finalize handler is supposed
|
to other member objects. The second phase, executed by the finalize handler is supposed
|
||||||
to complete the object's destruction process. Object methods should be able to run
|
to complete the object's destruction process. Object methods should be able to run
|
||||||
without program error (that is, without segfault :) in-between the two phases.
|
without program error in-between the two phases.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -410,8 +413,8 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Attentive readers might now have understood one of the rules about the dispose handler
|
This explains one of the rules about the dispose handler stated earlier:
|
||||||
we stated a bit sooner: the dispose handler can be invoked multiple times. Let's say we
|
the dispose handler can be invoked multiple times. Let's say we
|
||||||
have a reference count cycle: object A references B which itself references object A.
|
have a reference count cycle: object A references B which itself references object A.
|
||||||
Let's say we have detected the cycle and we want to destroy the two objects. One way to
|
Let's say we have detected the cycle and we want to destroy the two objects. One way to
|
||||||
do this would be to invoke <function><link linkend="g-object-run-dispose">g_object_run_dispose</link></function> on one of the
|
do this would be to invoke <function><link linkend="g-object-run-dispose">g_object_run_dispose</link></function> on one of the
|
||||||
@ -442,13 +445,12 @@ MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);
|
|||||||
One of GObject's nice features is its generic get/set mechanism for object
|
One of GObject's nice features is its generic get/set mechanism for object
|
||||||
properties. When an object
|
properties. When an object
|
||||||
is instantiated, the object's <function>class_init</function> handler should be used to register
|
is instantiated, the object's <function>class_init</function> handler should be used to register
|
||||||
the object's properties with <function><link linkend="g-object-class-install-properties">g_object_class_install_properties</link></function>
|
the object's properties with <function><link linkend="g-object-class-install-properties">g_object_class_install_properties</link></function>.
|
||||||
(implemented in <filename>gobject.c</filename>).
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The best way to understand how object properties work is by looking at a real example
|
The best way to understand how object properties work is by looking at a real example
|
||||||
on how it is used:
|
of how it is used:
|
||||||
<informalexample><programlisting>
|
<informalexample><programlisting>
|
||||||
/************************************************/
|
/************************************************/
|
||||||
/* Implementation */
|
/* Implementation */
|
||||||
@ -552,7 +554,7 @@ maman_bar_class_init (MamanBarClass *klass)
|
|||||||
GObject *bar;
|
GObject *bar;
|
||||||
GValue val = G_VALUE_INIT;
|
GValue val = G_VALUE_INIT;
|
||||||
|
|
||||||
bar = g_object_new (MAMAN_TYPE_SUBBAR, NULL);
|
bar = g_object_new (MAMAN_TYPE_BAR, NULL);
|
||||||
|
|
||||||
g_value_init (&val, G_TYPE_CHAR);
|
g_value_init (&val, G_TYPE_CHAR);
|
||||||
g_value_set_char (&val, 11);
|
g_value_set_char (&val, 11);
|
||||||
@ -567,14 +569,15 @@ g_value_unset (&val);
|
|||||||
<para>
|
<para>
|
||||||
<function><link linkend="g-object-set-property">g_object_set_property</link></function> first ensures a property
|
<function><link linkend="g-object-set-property">g_object_set_property</link></function> first ensures a property
|
||||||
with this name was registered in bar's <function>class_init</function> handler. If so it walks the class hierarchy,
|
with this name was registered in bar's <function>class_init</function> handler. If so it walks the class hierarchy,
|
||||||
from bottom, most derived type, to top, fundamental type to find the class
|
from bottom-most most-derived type, to top-most fundamental type to find the class
|
||||||
which registered that property. It then tries to convert the user-provided GValue
|
which registered that property. It then tries to convert the user-provided
|
||||||
into a GValue whose type is that of the associated property.
|
<link linkend="GValue"><type>GValue</type></link>
|
||||||
|
into a <type>GValue</type> whose type is that of the associated property.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If the user provides a signed char GValue, as is shown
|
If the user provides a <type>signed char</type> <type>GValue</type>, as is shown
|
||||||
here, and if the object's property was registered as an unsigned int,
|
here, and if the object's property was registered as an <type>unsigned int</type>,
|
||||||
<function><link linkend="g-value-transform">g_value_transform</link></function> will try to transform the input signed char into
|
<function><link linkend="g-value-transform">g_value_transform</link></function> will try to transform the input signed char into
|
||||||
an unsigned int. Of course, the success of the transformation depends on the availability
|
an unsigned int. Of course, the success of the transformation depends on the availability
|
||||||
of the required transform function. In practice, there will almost always be a transformation
|
of the required transform function. In practice, there will almost always be a transformation
|
||||||
@ -601,8 +604,9 @@ g_value_unset (&val);
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
If the user's GValue had been set to a valid value, <function><link linkend="g-object-set-property">g_object_set_property</link></function>
|
If the user's GValue had been set to a valid value, <function><link linkend="g-object-set-property">g_object_set_property</link></function>
|
||||||
would have proceeded with calling the object's set_property class method. Here, since our
|
would have proceeded with calling the object's
|
||||||
implementation of Foo did override this method, the code path would jump to
|
<function>set_property</function> class method. Here, since our
|
||||||
|
implementation of <type>Foo</type> did override this method, execution would jump to
|
||||||
<function>foo_set_property</function> after having retrieved from the
|
<function>foo_set_property</function> after having retrieved from the
|
||||||
<link linkend="GParamSpec"><type>GParamSpec</type></link> the <emphasis>param_id</emphasis>
|
<link linkend="GParamSpec"><type>GParamSpec</type></link> the <emphasis>param_id</emphasis>
|
||||||
<footnote>
|
<footnote>
|
||||||
@ -619,7 +623,8 @@ g_value_unset (&val);
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Once the property has been set by the object's set_property class method, the code path
|
Once the property has been set by the object's
|
||||||
|
<function>set_property</function> class method, execution
|
||||||
returns to <function><link linkend="g-object-set-property">g_object_set_property</link></function> which makes sure that
|
returns to <function><link linkend="g-object-set-property">g_object_set_property</link></function> which makes sure that
|
||||||
the "notify" signal is emitted on the object's instance with the changed property as
|
the "notify" signal is emitted on the object's instance with the changed property as
|
||||||
parameter unless notifications were frozen by <function><link linkend="g-object-freeze-notify">g_object_freeze_notify</link></function>.
|
parameter unless notifications were frozen by <function><link linkend="g-object-freeze-notify">g_object_freeze_notify</link></function>.
|
||||||
@ -627,11 +632,14 @@ g_value_unset (&val);
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
<function><link linkend="g-object-thaw-notify">g_object_thaw_notify</link></function> can be used to re-enable notification of
|
<function><link linkend="g-object-thaw-notify">g_object_thaw_notify</link></function> can be used to re-enable notification of
|
||||||
property modifications through the "notify" signal. It is important to remember that
|
property modifications through the
|
||||||
|
<link linkend="GObject-notify"><type>“notify”</type></link> signal. It is important to remember that
|
||||||
even if properties are changed while property change notification is frozen, the "notify"
|
even if properties are changed while property change notification is frozen, the "notify"
|
||||||
signal will be emitted once for each of these changed properties as soon as the property
|
signal will be emitted once for each of these changed properties as soon as the property
|
||||||
change notification is thawed: no property change is lost for the "notify" signal. Signal
|
change notification is thawed: no property change is lost for the "notify"
|
||||||
can only be delayed by the notification freezing mechanism.
|
signal, although multiple notifications for a single property are
|
||||||
|
compressed. Signals can only be delayed by the notification freezing
|
||||||
|
mechanism.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -663,25 +671,28 @@ g_object_set (G_OBJECT (foo),
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Of course, the _get versions are also available: <function><link linkend="g-object-get">g_object_get</link></function>
|
Equivalent <function>_get</function> versions are also available:
|
||||||
|
<function><link linkend="g-object-get">g_object_get</link></function>
|
||||||
and <function><link linkend="g-object-get-valist">g_object_get_valist</link></function> (variadic version) can be used to get numerous
|
and <function><link linkend="g-object-get-valist">g_object_get_valist</link></function> (variadic version) can be used to get numerous
|
||||||
properties at once.
|
properties at once.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
These high level functions have one drawback - they don't provide a return result.
|
These high level functions have one drawback — they don't provide a return value.
|
||||||
One should pay attention to the argument types and ranges when using them.
|
One should pay attention to the argument types and ranges when using them.
|
||||||
A known source of errors is to e.g. pass a gfloat instead of a gdouble and thus
|
A known source of errors is to pass a different type from what the
|
||||||
shifting all subsequent parameters by four bytes. Also forgetting the terminating
|
property expects; for instance, passing an integer when the property
|
||||||
NULL will lead to unexpected behaviour.
|
expects a floating point value and thus shifting all subsequent parameters
|
||||||
|
by some number of bytes. Also forgetting the terminating
|
||||||
|
<literal>NULL</literal> will lead to undefined behaviour.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Really attentive readers now understand how <function><link linkend="g-object-new">g_object_new</link></function>,
|
This explains how <function><link linkend="g-object-new">g_object_new</link></function>,
|
||||||
<function><link linkend="g-object-newv">g_object_newv</link></function> and <function><link linkend="g-object-new-valist">g_object_new_valist</link></function>
|
<function><link linkend="g-object-newv">g_object_newv</link></function> and <function><link linkend="g-object-new-valist">g_object_new_valist</link></function>
|
||||||
work: they parse the user-provided variable number of parameters and invoke
|
work: they parse the user-provided variable number of parameters and invoke
|
||||||
<function><link linkend="g-object-set">g_object_set</link></function> on the parameters only after the object has been successfully constructed.
|
<function><link linkend="g-object-set">g_object_set</link></function> on the parameters only after the object has been successfully constructed.
|
||||||
Of course, the "notify" signal will be emitted for each property set.
|
The "notify" signal will be emitted for each property set.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
@ -16,11 +16,11 @@
|
|||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem><para>a function pointer (the callback itself) whose prototype looks like:
|
<listitem><para>a function pointer (the callback itself) whose prototype looks like:
|
||||||
<informalexample><programlisting>
|
<informalexample><programlisting>
|
||||||
return_type function_callback (... , gpointer user_data);
|
return_type function_callback (… , gpointer user_data);
|
||||||
</programlisting></informalexample>
|
</programlisting></informalexample>
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
the user_data pointer which is passed to the callback upon invocation of the closure
|
the <parameter>user_data</parameter> pointer which is passed to the callback upon invocation of the closure
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
a function pointer which represents the destructor of the closure: whenever the
|
a function pointer which represents the destructor of the closure: whenever the
|
||||||
@ -32,7 +32,7 @@ return_type function_callback (... , gpointer user_data);
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
The <link linkend="GClosure"><type>GClosure</type></link> structure represents the common functionality of all
|
The <link linkend="GClosure"><type>GClosure</type></link> structure represents the common functionality of all
|
||||||
closure implementations: there exists a different Closure implementation for
|
closure implementations: there exists a different closure implementation for
|
||||||
each separate runtime which wants to use the GObject type system.
|
each separate runtime which wants to use the GObject type system.
|
||||||
<footnote><para>
|
<footnote><para>
|
||||||
In practice, closures sit at the boundary of language runtimes: if you are
|
In practice, closures sit at the boundary of language runtimes: if you are
|
||||||
@ -79,32 +79,27 @@ return_type function_callback (... , gpointer user_data);
|
|||||||
If you are using C or C++
|
If you are using C or C++
|
||||||
to connect a callback to a given event, you will either use simple <link linkend="GCClosure"><type>GCClosure</type></link>s
|
to connect a callback to a given event, you will either use simple <link linkend="GCClosure"><type>GCClosure</type></link>s
|
||||||
which have a pretty minimal API or the even simpler <function><link linkend="g-signal-connect">g_signal_connect</link></function>
|
which have a pretty minimal API or the even simpler <function><link linkend="g-signal-connect">g_signal_connect</link></function>
|
||||||
functions (which will be presented a bit later :).
|
functions (which will be presented a bit later).
|
||||||
<informalexample><programlisting>
|
|
||||||
GClosure *g_cclosure_new (GCallback callback_func,
|
|
||||||
gpointer user_data,
|
|
||||||
GClosureNotify destroy_data);
|
|
||||||
GClosure *g_cclosure_new_swap (GCallback callback_func,
|
|
||||||
gpointer user_data,
|
|
||||||
GClosureNotify destroy_data);
|
|
||||||
GClosure *g_signal_type_cclosure_new (GType itype,
|
|
||||||
guint struct_offset);
|
|
||||||
</programlisting></informalexample>
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<function><link linkend="g-cclosure-new">g_cclosure_new</link></function> will create a new closure which can invoke the
|
<function><link linkend="g-cclosure-new">g_cclosure_new</link></function> will create a new closure which can invoke the
|
||||||
user-provided callback_func with the user-provided user_data as last parameter. When the closure
|
user-provided callback_func with the user-provided
|
||||||
is finalized (second stage of the destruction process), it will invoke the destroy_data function
|
<parameter>user_data</parameter> as its last parameter. When the closure
|
||||||
if the user has supplied one.
|
is finalized (second stage of the destruction process), it will invoke
|
||||||
|
the <parameter>destroy_data</parameter> function if the user has
|
||||||
|
supplied one.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<function><link linkend="g-cclosure-new-swap">g_cclosure_new_swap</link></function> will create a new closure which can invoke the
|
<function><link linkend="g-cclosure-new-swap">g_cclosure_new_swap</link></function> will create a new closure which can invoke the
|
||||||
user-provided callback_func with the user-provided user_data as first parameter (instead of being the
|
user-provided <parameter>callback_func</parameter> with the
|
||||||
|
user-provided <parameter>user_data</parameter> as its first parameter
|
||||||
|
(instead of being the
|
||||||
last parameter as with <function><link linkend="g-cclosure-new">g_cclosure_new</link></function>). When the closure
|
last parameter as with <function><link linkend="g-cclosure-new">g_cclosure_new</link></function>). When the closure
|
||||||
is finalized (second stage of the destruction process), it will invoke the destroy_data
|
is finalized (second stage of the destruction process), it will invoke
|
||||||
function if the user has supplied one.
|
the <parameter>destroy_data</parameter> function if the user has
|
||||||
|
supplied one.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
@ -126,8 +121,17 @@ GClosure *g_signal_type_cclosure_new (GType itype,
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The following code implements a simple marshaller in C for a C function which takes an
|
A generic C closure marshaller is available as
|
||||||
integer as first parameter and returns void.
|
<link linkend="g-cclosure-marshal-generic"><function>g_cclosure_marshal_generic</function></link>
|
||||||
|
which implements marshalling for all function types using libffi. Custom
|
||||||
|
marshallers for different types are not needed.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
An example of a custom marshaller is given below, illustrating how
|
||||||
|
<type>GValue</type>s can be converted to a C function call. The
|
||||||
|
marshaller is for a C function which takes an integer as its first
|
||||||
|
parameter and returns void.
|
||||||
<informalexample><programlisting>
|
<informalexample><programlisting>
|
||||||
g_cclosure_marshal_VOID__INT (GClosure *closure,
|
g_cclosure_marshal_VOID__INT (GClosure *closure,
|
||||||
GValue *return_value,
|
GValue *return_value,
|
||||||
@ -158,13 +162,11 @@ g_cclosure_marshal_VOID__INT (GClosure *closure,
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Of course, there exist other kinds of marshallers. For example, James Henstridge
|
There exist other kinds of marshallers, for example there is a generic
|
||||||
wrote a generic Python marshaller which is used by all Python closures (a Python closure
|
Python marshaller which is used by all Python closures (a Python closure
|
||||||
is used to have Python-based callback be invoked by the closure invocation process).
|
is used to invoke a callback written in Python). This Python marshaller
|
||||||
This Python marshaller transforms the input GValue list representing the function
|
transforms the input GValue list representing the function parameters
|
||||||
parameters into a Python tuple which is the equivalent structure in Python (you can
|
into a Python tuple which is the equivalent structure in Python.
|
||||||
look in <function>pyg_closure_marshal</function> in <filename>pygtype.c</filename>
|
|
||||||
in the <emphasis>pygobject</emphasis> module in the GNOME source code repository).
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
@ -177,8 +179,8 @@ g_cclosure_marshal_VOID__INT (GClosure *closure,
|
|||||||
GObject's signals have nothing to do with standard UNIX signals: they connect
|
GObject's signals have nothing to do with standard UNIX signals: they connect
|
||||||
arbitrary application-specific events with any number of listeners.
|
arbitrary application-specific events with any number of listeners.
|
||||||
For example, in GTK+, every user event (keystroke or mouse move) is received
|
For example, in GTK+, every user event (keystroke or mouse move) is received
|
||||||
from the X server and generates a GTK+ event under the form of a signal emission
|
from the windowing system and generates a GTK+ event in the form of a signal emission
|
||||||
on a given object instance.
|
on the widget object instance.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -195,7 +197,7 @@ g_cclosure_marshal_VOID__INT (GClosure *closure,
|
|||||||
connected to this signal on this type instance will be invoked. All the closures
|
connected to this signal on this type instance will be invoked. All the closures
|
||||||
connected to such a signal represent callbacks whose signature looks like:
|
connected to such a signal represent callbacks whose signature looks like:
|
||||||
<informalexample><programlisting>
|
<informalexample><programlisting>
|
||||||
return_type function_callback (gpointer instance, ... , gpointer user_data);
|
return_type function_callback (gpointer instance, …, gpointer user_data);
|
||||||
</programlisting></informalexample>
|
</programlisting></informalexample>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@ -221,43 +223,47 @@ guint g_signal_newv (const gchar *signal_name,
|
|||||||
simple:
|
simple:
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
signal_name: is a string which can be used to uniquely identify a given signal.
|
<parameter>signal_name</parameter>: is a string which can be used to uniquely identify a given signal.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
itype: is the instance type on which this signal can be emitted.
|
<parameter>itype</parameter>: is the instance type on which this signal can be emitted.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
signal_flags: partly defines the order in which closures which were connected to the
|
<parameter>signal_flags</parameter>: partly defines the order in which closures which were connected to the
|
||||||
signal are invoked.
|
signal are invoked.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
class_closure: this is the default closure for the signal: if it is not NULL upon
|
<parameter>class_closure</parameter>: this is the default closure for the signal: if it is not NULL upon
|
||||||
the signal emission, it will be invoked upon this emission of the signal. The
|
the signal emission, it will be invoked upon this emission of the signal. The
|
||||||
moment where this closure is invoked compared to other closures connected to that
|
moment where this closure is invoked compared to other closures connected to that
|
||||||
signal depends partly on the signal_flags.
|
signal depends partly on the signal_flags.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
accumulator: this is a function pointer which is invoked after each closure
|
<parameter>accumulator</parameter>: this is a function pointer which is invoked after each closure
|
||||||
has been invoked. If it returns FALSE, signal emission is stopped. If it returns
|
has been invoked. If it returns FALSE, signal emission is stopped. If it returns
|
||||||
TRUE, signal emission proceeds normally. It is also used to compute the return
|
TRUE, signal emission proceeds normally. It is also used to compute the return
|
||||||
value of the signal based on the return value of all the invoked closures.
|
value of the signal based on the return value of all the invoked closures.
|
||||||
|
For example, an accumulator could ignore
|
||||||
|
<literal>NULL</literal> returns from closures; or it
|
||||||
|
could build a list of the values returned by the
|
||||||
|
closures.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
accumulator_data: this pointer will be passed down to each invocation of the
|
<parameter>accumulator_data</parameter>: this pointer will be passed down to each invocation of the
|
||||||
accumulator during emission.
|
accumulator during emission.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
c_marshaller: this is the default C marshaller for any closure which is connected to
|
<parameter>c_marshaller</parameter>: this is the default C marshaller for any closure which is connected to
|
||||||
this signal.
|
this signal.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
return_type: this is the type of the return value of the signal.
|
<parameter>return_type</parameter>: this is the type of the return value of the signal.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
n_params: this is the number of parameters this signal takes.
|
<parameter>n_params</parameter>: this is the number of parameters this signal takes.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
param_types: this is an array of GTypes which indicate the type of each parameter
|
<parameter>param_types</parameter>: this is an array of GTypes which indicate the type of each parameter
|
||||||
of the signal. The length of this array is indicated by n_params.
|
of the signal. The length of this array is indicated by n_params.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
@ -279,12 +285,12 @@ guint g_signal_newv (const gchar *signal_name,
|
|||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
You can register a class closure at signal registration: this is a
|
You can register a class closure at signal registration: this is a
|
||||||
system-wide operation. i.e.: the class_closure will be invoked during each emission
|
system-wide operation. i.e.: the class closure will be invoked during each emission
|
||||||
of a given signal on all the instances of the type which supports that signal.
|
of a given signal on <emphasis>any</emphasis> of the instances of the type which supports that signal.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
You can use <function><link linkend="g-signal-override-class-closure">g_signal_override_class_closure</link></function> which
|
You can use <function><link linkend="g-signal-override-class-closure">g_signal_override_class_closure</link></function> which
|
||||||
overrides the class_closure of a given type. It is possible to call this function
|
overrides the class closure of a given type. It is possible to call this function
|
||||||
only on a derived type of the type on which the signal was registered.
|
only on a derived type of the type on which the signal was registered.
|
||||||
This function is of use only to language bindings.
|
This function is of use only to language bindings.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
@ -318,101 +324,90 @@ void g_signal_emitv (const GValue *instance_and_params,
|
|||||||
</programlisting></informalexample>
|
</programlisting></informalexample>
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
The instance_and_params array of GValues contains the list of input
|
The <parameter>instance_and_params</parameter> array of GValues contains the list of input
|
||||||
parameters to the signal. The first element of the array is the
|
parameters to the signal. The first element of the array is the
|
||||||
instance pointer on which to invoke the signal. The following elements of
|
instance pointer on which to invoke the signal. The following elements of
|
||||||
the array contain the list of parameters to the signal.
|
the array contain the list of parameters to the signal.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
signal_id identifies the signal to invoke.
|
<parameter>signal_id</parameter> identifies the signal to invoke.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
detail identifies the specific detail of the signal to invoke. A detail is a kind of
|
<parameter>detail</parameter> identifies the specific detail of the signal to invoke. A detail is a kind of
|
||||||
magic token/argument which is passed around during signal emission and which is used
|
magic token/argument which is passed around during signal emission and which is used
|
||||||
by closures connected to the signal to filter out unwanted signal emissions. In most
|
by closures connected to the signal to filter out unwanted signal emissions. In most
|
||||||
cases, you can safely set this value to zero. See <xref linkend="signal-detail"/> for
|
cases, you can safely set this value to zero. See <xref linkend="signal-detail"/> for
|
||||||
more details about this parameter.
|
more details about this parameter.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
return_value holds the return value of the last closure invoked during emission if
|
<parameter>return_value</parameter> holds the return value of the last closure invoked during emission if
|
||||||
no accumulator was specified. If an accumulator was specified during signal creation,
|
no accumulator was specified. If an accumulator was specified during signal creation,
|
||||||
this accumulator is used to calculate the return_value as a function of the return
|
this accumulator is used to calculate the return value as a function of the return
|
||||||
values of all the closures invoked during emission.
|
values of all the closures invoked during emission.
|
||||||
<footnote><para>
|
|
||||||
James (again!!) gives a few non-trivial examples of accumulators:
|
|
||||||
<quote>
|
|
||||||
For instance, you may have an accumulator that ignores NULL returns from
|
|
||||||
closures, and only accumulates the non-NULL ones. Another accumulator may try
|
|
||||||
to return the list of values returned by the closures.
|
|
||||||
</quote>
|
|
||||||
</para></footnote>
|
|
||||||
If no closure is invoked during
|
If no closure is invoked during
|
||||||
emission, the return_value is nonetheless initialized to zero/null.
|
emission, the <parameter>return_value</parameter> is nonetheless initialized to zero/null.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Internally, the GValue array is passed to the emission function proper,
|
|
||||||
<function>signal_emit_unlocked_R</function> (implemented in <filename>gsignal.c</filename>).
|
|
||||||
Signal emission can be decomposed in 5 steps:
|
Signal emission can be decomposed in 5 steps:
|
||||||
<itemizedlist>
|
<orderedlist>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
<emphasis>RUN_FIRST</emphasis>: if the G_SIGNAL_RUN_FIRST flag was used
|
<literal>RUN_FIRST</literal>: if the
|
||||||
during signal registration and if there exist a class_closure for this signal,
|
<link linkend="G-SIGNAL-RUN-FIRST:CAPS"><literal>G_SIGNAL_RUN_FIRST</literal></link> flag was used
|
||||||
the class_closure is invoked. Jump to <emphasis>EMISSION_HOOK</emphasis> state.
|
during signal registration and if there exists a class closure for this signal,
|
||||||
|
the class closure is invoked.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
<emphasis>EMISSION_HOOK</emphasis>: if any emission hook was added to
|
<literal>EMISSION_HOOK</literal>: if any emission hook was added to
|
||||||
the signal, they are invoked from first to last added. Accumulate return values
|
the signal, they are invoked from first to last added. Accumulate return values.
|
||||||
and jump to <emphasis>HANDLER_RUN_FIRST</emphasis> state.
|
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
<emphasis>HANDLER_RUN_FIRST</emphasis>: if any closure were connected
|
<literal>HANDLER_RUN_FIRST</literal>: if any closure were connected
|
||||||
with the <function><link linkend="g-signal-connect">g_signal_connect</link></function> family of
|
with the <function><link linkend="g-signal-connect">g_signal_connect</link></function> family of
|
||||||
functions, and if they are not blocked (with the <function><link linkend="g-signal-handler-block">g_signal_handler_block</link></function>
|
functions, and if they are not blocked (with the <function><link linkend="g-signal-handler-block">g_signal_handler_block</link></function>
|
||||||
family of functions) they are run here, from first to last connected.
|
family of functions) they are run here, from first to last connected.
|
||||||
Jump to <emphasis>RUN_LAST</emphasis> state.
|
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
<emphasis>RUN_LAST</emphasis>: if the G_SIGNAL_RUN_LAST
|
<literal>RUN_LAST</literal>: if the <literal>G_SIGNAL_RUN_LAST</literal>
|
||||||
flag was set during registration and if a class_closure
|
flag was set during registration and if a class closure
|
||||||
was set, it is invoked here. Jump to
|
was set, it is invoked here.
|
||||||
<emphasis>HANDLER_RUN_LAST</emphasis> state.
|
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
<emphasis>HANDLER_RUN_LAST</emphasis>: if any closure were connected
|
<literal>HANDLER_RUN_LAST</literal>: if any closure were connected
|
||||||
with the <function>g_signal_connect_after</function> family of
|
with the <function>g_signal_connect_after</function> family of
|
||||||
functions, if they were not invoked during HANDLER_RUN_FIRST and if they
|
functions, if they were not invoked during <literal>HANDLER_RUN_FIRST</literal> and if they
|
||||||
are not blocked, they are run here, from first to last connected.
|
are not blocked, they are run here, from first to last connected.
|
||||||
Jump to <emphasis>RUN_CLEANUP</emphasis> state.
|
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
<emphasis>RUN_CLEANUP</emphasis>: if the G_SIGNAL_RUN_CLEANUP flag
|
<literal>RUN_CLEANUP</literal>: if the <literal>G_SIGNAL_RUN_CLEANUP</literal> flag
|
||||||
was set during registration and if a class_closure was set,
|
was set during registration and if a class closure was set,
|
||||||
it is invoked here. Signal emission is completed here.
|
it is invoked here. Signal emission is completed here.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
</itemizedlist>
|
</orderedlist>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If, at any point during emission (except in RUN_CLEANUP state), one of the
|
If, at any point during emission (except in <literal>RUN_CLEANUP</literal> state), one of the
|
||||||
closures or emission hook stops the signal emission with
|
closures or emission hook stops the signal emission with
|
||||||
<function><link linkend="g-signal-stop-emission">g_signal_stop_emission</link></function>,
|
<function><link linkend="g-signal-stop-emission">g_signal_stop_emission</link></function>,
|
||||||
emission jumps to CLEANUP state.
|
emission jumps to <literal>RUN_CLEANUP</literal> state.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If, at any point during emission, one of the closures or emission hook
|
If, at any point during emission, one of the closures or emission hook
|
||||||
emits the same signal on the same instance, emission is restarted from
|
emits the same signal on the same instance, emission is restarted from
|
||||||
the RUN_FIRST state.
|
the <literal>RUN_FIRST</literal> state.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The accumulator function is invoked in all states, after invocation
|
The accumulator function is invoked in all states, after invocation
|
||||||
of each closure (except in EMISSION_HOOK and CLEANUP). It accumulates
|
of each closure (except in <literal>RUN_EMISSION_HOOK</literal> and
|
||||||
|
<literal>RUN_CLEANUP</literal>). It accumulates
|
||||||
the closure return value into the signal return value and returns TRUE or
|
the closure return value into the signal return value and returns TRUE or
|
||||||
FALSE. If, at any point, it does not return TRUE, emission jumps to CLEANUP state.
|
FALSE. If, at any point, it does not return TRUE, emission jumps
|
||||||
|
to <literal>RUN_CLEANUP</literal> state.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -428,85 +423,60 @@ void g_signal_emitv (const GValue *instance_and_params,
|
|||||||
|
|
||||||
<para>All the functions related to signal emission or signal connection have a parameter
|
<para>All the functions related to signal emission or signal connection have a parameter
|
||||||
named the <emphasis>detail</emphasis>. Sometimes, this parameter is hidden by the API
|
named the <emphasis>detail</emphasis>. Sometimes, this parameter is hidden by the API
|
||||||
but it is always there, under one form or another.
|
but it is always there, in one form or another.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Of the three main connection functions,
|
Of the three main connection functions,
|
||||||
only one has an explicit detail parameter as a <link linkend="GQuark"><type>GQuark</type></link>
|
only one has an explicit detail parameter as a <link linkend="GQuark"><type>GQuark</type></link>:
|
||||||
|
<link linkend="g-signal-connect-closure-by-id"><function>g_signal_connect_closure_by_id</function></link>.
|
||||||
<footnote>
|
<footnote>
|
||||||
<para>A GQuark is an integer which uniquely represents a string. It is possible to transform
|
<para>A GQuark is an integer which uniquely represents a string. It is possible to transform
|
||||||
back and forth between the integer and string representations with the functions
|
back and forth between the integer and string representations with the functions
|
||||||
<function><link linkend="g-quark-from-string">g_quark_from_string</link></function> and <function><link linkend="g-quark-to-string">g_quark_to_string</link></function>.
|
<function><link linkend="g-quark-from-string">g_quark_from_string</link></function> and <function><link linkend="g-quark-to-string">g_quark_to_string</link></function>.
|
||||||
</para>
|
</para>
|
||||||
</footnote>:
|
</footnote>
|
||||||
<informalexample><programlisting>
|
</para>
|
||||||
gulong g_signal_connect_closure_by_id (gpointer instance,
|
<para>
|
||||||
guint signal_id,
|
The two other functions,
|
||||||
GQuark detail,
|
<link linkend="g-signal-connect-closure"><function>g_signal_connect_closure</function></link> and
|
||||||
GClosure *closure,
|
<link linkend="g-signal-connect-data"><function>g_signal_connect_data</function></link>
|
||||||
gboolean after);
|
hide the detail parameter in the signal name identification.
|
||||||
</programlisting></informalexample>
|
Their <parameter>detailed_signal</parameter> parameter is a
|
||||||
The two other functions hide the detail parameter in the signal name identification:
|
string which identifies the name of the signal to connect to.
|
||||||
<informalexample><programlisting>
|
The format of this string should match
|
||||||
gulong g_signal_connect_closure (gpointer instance,
|
<emphasis>signal_name::detail_name</emphasis>. For example,
|
||||||
const gchar *detailed_signal,
|
connecting to the signal named
|
||||||
GClosure *closure,
|
<emphasis>notify::cursor_position</emphasis> will actually
|
||||||
gboolean after);
|
connect to the signal named <emphasis>notify</emphasis> with the
|
||||||
gulong g_signal_connect_data (gpointer instance,
|
<emphasis>cursor_position</emphasis> detail.
|
||||||
const gchar *detailed_signal,
|
|
||||||
GCallback c_handler,
|
|
||||||
gpointer data,
|
|
||||||
GClosureNotify destroy_data,
|
|
||||||
GConnectFlags connect_flags);
|
|
||||||
</programlisting></informalexample>
|
|
||||||
Their detailed_signal parameter is a string which identifies the name of the signal
|
|
||||||
to connect to. However, the format of this string is structured to look like
|
|
||||||
<emphasis>signal_name::detail_name</emphasis>. Connecting to the signal
|
|
||||||
named <emphasis>notify::cursor_position</emphasis> will actually connect to the signal
|
|
||||||
named <emphasis>notify</emphasis> with the <emphasis>cursor_position</emphasis> name.
|
|
||||||
Internally, the detail string is transformed to a GQuark if it is present.
|
Internally, the detail string is transformed to a GQuark if it is present.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Of the four main signal emission functions, three have an explicit detail parameter as a
|
Of the four main signal emission functions, one hides it in its
|
||||||
|
signal name parameter:
|
||||||
|
<link linkend="g-signal-connect"><function>g_signal_connect</function></link>.
|
||||||
|
The other three have an explicit detail parameter as a
|
||||||
<link linkend="GQuark"><type>GQuark</type></link> again:
|
<link linkend="GQuark"><type>GQuark</type></link> again:
|
||||||
<informalexample><programlisting>
|
<link linkend="g-signal-emit"><function>g_signal_emit</function></link>,
|
||||||
void g_signal_emitv (const GValue *instance_and_params,
|
<link linkend="g-signal-emitv"><function>g_signal_emitv</function></link> and
|
||||||
guint signal_id,
|
<link linkend="g-signal-emit-valist"><function>g_signal_emit_valist</function></link>.
|
||||||
GQuark detail,
|
|
||||||
GValue *return_value);
|
|
||||||
void g_signal_emit_valist (gpointer instance,
|
|
||||||
guint signal_id,
|
|
||||||
GQuark detail,
|
|
||||||
va_list var_args);
|
|
||||||
void g_signal_emit (gpointer instance,
|
|
||||||
guint signal_id,
|
|
||||||
GQuark detail,
|
|
||||||
...);
|
|
||||||
</programlisting></informalexample>
|
|
||||||
The fourth function hides it in its signal name parameter:
|
|
||||||
<informalexample><programlisting>
|
|
||||||
void g_signal_emit_by_name (gpointer instance,
|
|
||||||
const gchar *detailed_signal,
|
|
||||||
...);
|
|
||||||
</programlisting></informalexample>
|
|
||||||
The format of the detailed_signal parameter is exactly the same as the format used by
|
|
||||||
the <function><link linkend="g-signal-connect">g_signal_connect</link></function> functions: <emphasis>signal_name::detail_name</emphasis>.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If a detail is provided by the user to the emission function, it is used during emission to match
|
If a detail is provided by the user to the emission function, it is used during emission to match
|
||||||
against the closures which also provide a detail.
|
against the closures which also provide a detail.
|
||||||
If the closures' detail does not match the detail provided by the user, they will not be invoked
|
If a closure's detail does not match the detail provided by the user, it
|
||||||
(even though they are connected to a signal which is being emitted).
|
will not be invoked (even though it is connected to a signal which is
|
||||||
|
being emitted).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
This completely optional filtering mechanism is mainly used as an optimization for signals
|
This completely optional filtering mechanism is mainly used as an optimization for signals
|
||||||
which are often emitted for many different reasons: the clients can filter out which events they are
|
which are often emitted for many different reasons: the clients can filter out which events they are
|
||||||
interested in before the closure's marshalling code runs. For example, this is used extensively
|
interested in before the closure's marshalling code runs. For example, this is used extensively
|
||||||
by the <emphasis>notify</emphasis> signal of GObject: whenever a property is modified on a GObject,
|
by the <link linkend="GObject-notify"><structfield>notify</structfield></link> signal of GObject: whenever a property is modified on a GObject,
|
||||||
instead of just emitting the <emphasis>notify</emphasis> signal, GObject associates as a detail to this
|
instead of just emitting the <emphasis>notify</emphasis> signal, GObject associates as a detail to this
|
||||||
signal emission the name of the property modified. This allows clients who wish to be notified of changes
|
signal emission the name of the property modified. This allows clients who wish to be notified of changes
|
||||||
to only one property to filter most events before receiving them.
|
to only one property to filter most events before receiving them.
|
||||||
@ -514,7 +484,7 @@ void g_signal_emit_by_name (gpointer instance,
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
As a simple rule, users can and should set the detail parameter to zero: this will disable completely
|
As a simple rule, users can and should set the detail parameter to zero: this will disable completely
|
||||||
this optional filtering.
|
this optional filtering for that signal.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
@ -45,23 +45,16 @@ GType g_type_register_fundamental (GType type_id,
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<function><link linkend="g-type-register-static">g_type_register_static</link></function> and
|
<function><link linkend="g-type-register-static">g_type_register_static</link></function>,
|
||||||
|
<function><link linkend="g-type-register-dynamic">g_type_register_dynamic</link></function> and
|
||||||
<function><link linkend="g-type-register-fundamental">g_type_register_fundamental</link></function>
|
<function><link linkend="g-type-register-fundamental">g_type_register_fundamental</link></function>
|
||||||
are the C functions, defined in
|
are the C functions, defined in
|
||||||
<filename>gtype.h</filename> and implemented in <filename>gtype.c</filename>
|
<filename>gtype.h</filename> and implemented in <filename>gtype.c</filename>
|
||||||
which you should use to register a new <link linkend="GType"><type>GType</type></link> in the program's type system.
|
which you should use to register a new <link linkend="GType"><type>GType</type></link> in the program's type system.
|
||||||
It is not likely you will ever need to use
|
It is not likely you will ever need to use
|
||||||
<function><link linkend="g-type-register-fundamental">g_type_register_fundamental</link></function> (you have to be Tim Janik
|
<function><link linkend="g-type-register-fundamental">g_type_register_fundamental</link></function>
|
||||||
to do that) but in case you want to, the last chapter explains how to create
|
but in case you want to, the last chapter explains how to create
|
||||||
new fundamental types.
|
new fundamental types.
|
||||||
<footnote>
|
|
||||||
<para>
|
|
||||||
Please note that there exists another registration function: the
|
|
||||||
<function><link linkend="g-type-register-dynamic">g_type_register_dynamic</link></function>. We will not discuss this
|
|
||||||
function here since its use is very similar to the <function>_static</function>
|
|
||||||
version.
|
|
||||||
</para>
|
|
||||||
</footnote>
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -80,8 +73,8 @@ GType g_type_register_fundamental (GType type_id,
|
|||||||
class size: the class_size field in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>.
|
class size: the class_size field in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
class initialization functions (C++ constructor): the base_init and
|
class initialization functions (C++ constructor): the <function>base_init</function> and
|
||||||
class_init fields in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>.
|
<function>class_init</function> fields in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
class destruction functions (C++ destructor): the base_finalize and
|
class destruction functions (C++ destructor): the base_finalize and
|
||||||
@ -131,8 +124,7 @@ GType g_type_register_fundamental (GType type_id,
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
The following code shows how you can copy around a 64 bit integer, as well as a <link linkend="GObject"><type>GObject</type></link>
|
The following code shows how you can copy around a 64 bit integer, as well as a <link linkend="GObject"><type>GObject</type></link>
|
||||||
instance pointer (sample code for this is located in the source tarball for this document in
|
instance pointer:
|
||||||
<filename>sample/gtype/test.c</filename>):
|
|
||||||
<informalexample><programlisting>
|
<informalexample><programlisting>
|
||||||
static void test_int (void)
|
static void test_int (void)
|
||||||
{
|
{
|
||||||
@ -140,7 +132,7 @@ static void test_int (void)
|
|||||||
GValue b_value = G_VALUE_INIT;
|
GValue b_value = G_VALUE_INIT;
|
||||||
guint64 a, b;
|
guint64 a, b;
|
||||||
|
|
||||||
a = 0xdeadbeaf;
|
a = 0xdeadbeef;
|
||||||
|
|
||||||
g_value_init (&a_value, G_TYPE_UINT64);
|
g_value_init (&a_value, G_TYPE_UINT64);
|
||||||
g_value_set_uint64 (&a_value, a);
|
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_init (&obj_valb, G_TYPE_OBJECT);
|
||||||
|
|
||||||
/* g_value_copy's semantics for G_TYPE_OBJECT types is to copy the reference.
|
/* g_value_copy's semantics for G_TYPE_OBJECT types is to copy the reference.
|
||||||
This function thus calls g_object_ref.
|
* This function thus calls g_object_ref.
|
||||||
It is interesting to note that the assignment works here because
|
* It is interesting to note that the assignment works here because
|
||||||
MAMAN_TYPE_BAR is a G_TYPE_OBJECT.
|
* MAMAN_TYPE_BAR is a G_TYPE_OBJECT.
|
||||||
*/
|
*/
|
||||||
g_value_copy (&obj_vala, &obj_valb);
|
g_value_copy (&obj_vala, &obj_valb);
|
||||||
|
|
||||||
@ -188,39 +180,15 @@ static void test_object (void)
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The value_table used to specify these assignment functions is defined in
|
The value table used to specify these assignment functions is
|
||||||
<filename>gtype.h</filename> and is thoroughly described in the
|
documented in
|
||||||
API documentation provided with GObject (for once ;-) which is why we will
|
<link linkend="GTypeValueTable"><type>GTypeValueTable</type></link>.
|
||||||
not detail its exact semantics.
|
</para>
|
||||||
<informalexample><programlisting>
|
<para>
|
||||||
typedef struct _GTypeValueTable GTypeValueTable;
|
|
||||||
struct _GTypeValueTable
|
|
||||||
{
|
|
||||||
void (*value_init) (GValue *value);
|
|
||||||
void (*value_free) (GValue *value);
|
|
||||||
void (*value_copy) (const GValue *src_value,
|
|
||||||
GValue *dest_value);
|
|
||||||
/* varargs functionality (optional) */
|
|
||||||
gpointer (*value_peek_pointer) (const GValue *value);
|
|
||||||
gchar *collect_format;
|
|
||||||
gchar* (*collect_value) (GValue *value,
|
|
||||||
guint n_collect_values,
|
|
||||||
GTypeCValue *collect_values,
|
|
||||||
guint collect_flags);
|
|
||||||
gchar *lcopy_format;
|
|
||||||
gchar* (*lcopy_value) (const GValue *value,
|
|
||||||
guint n_collect_values,
|
|
||||||
GTypeCValue *collect_values,
|
|
||||||
guint collect_flags);
|
|
||||||
};
|
|
||||||
</programlisting></informalexample>
|
|
||||||
Interestingly, it is also very unlikely
|
Interestingly, it is also very unlikely
|
||||||
you will ever need to specify a value_table during type registration
|
you will ever need to specify a value_table during type registration
|
||||||
because these value_tables are inherited from the parent types for
|
because these value_tables are inherited from the parent types for
|
||||||
non-fundamental types which means that unless you want to write a
|
non-fundamental types.
|
||||||
fundamental type (not a great idea!), you will not need to provide
|
|
||||||
a new value_table since you will inherit the value_table structure
|
|
||||||
from your parent type.
|
|
||||||
</para>
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
@ -246,7 +214,7 @@ struct _GTypeValueTable
|
|||||||
<footnote>
|
<footnote>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Maman</emphasis> is the French word for <emphasis>mum</emphasis>
|
<emphasis>Maman</emphasis> is the French word for <emphasis>mum</emphasis>
|
||||||
or <emphasis>mother</emphasis> - nothing more and nothing less.
|
or <emphasis>mother</emphasis> — nothing more and nothing less.
|
||||||
</para>
|
</para>
|
||||||
</footnote>
|
</footnote>
|
||||||
|
|
||||||
@ -342,8 +310,7 @@ G_DEFINE_TYPE (MamanBar, maman_bar, G_TYPE_OBJECT)
|
|||||||
<para>
|
<para>
|
||||||
A lot of types are not instantiable by the type system and do not have
|
A lot of types are not instantiable by the type system and do not have
|
||||||
a class. Most of these types are fundamental trivial types such as <emphasis>gchar</emphasis>,
|
a class. Most of these types are fundamental trivial types such as <emphasis>gchar</emphasis>,
|
||||||
and are already registered in <function>_g_value_types_init</function>
|
and are already registered by GLib.
|
||||||
(in <filename>gvaluetypes.c</filename>).
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -412,7 +379,8 @@ G_DEFINE_TYPE (MamanBar, maman_bar, G_TYPE_OBJECT)
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
For example, the code below shows how you could register
|
For example, the code below shows how you could register
|
||||||
such a fundamental object type in the type system:
|
such a fundamental object type in the type system (using none of the
|
||||||
|
GObject convenience API):
|
||||||
<informalexample><programlisting>
|
<informalexample><programlisting>
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GObject parent;
|
GObject parent;
|
||||||
@ -509,7 +477,8 @@ typedef struct {
|
|||||||
The C standard mandates that the first field of a C structure is stored starting
|
The C standard mandates that the first field of a C structure is stored starting
|
||||||
in the first byte of the buffer used to hold the structure's fields in memory.
|
in the first byte of the buffer used to hold the structure's fields in memory.
|
||||||
This means that the first field of an instance of an object B is A's first field
|
This means that the first field of an instance of an object B is A's first field
|
||||||
which in turn is GTypeInstance's first field which in turn is g_class, a pointer
|
which in turn is <type>GTypeInstance</type>'s first field which in
|
||||||
|
turn is <structfield>g_class</structfield>, a pointer
|
||||||
to B's class structure.
|
to B's class structure.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@ -532,14 +501,11 @@ B *b;
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
instantiation of these types can be done with
|
instantiation of these types can be done with
|
||||||
<function><link linkend="g-type-create-instance">g_type_create_instance</link></function>:
|
<function><link linkend="g-type-create-instance">g_type_create_instance</link></function>,
|
||||||
<informalexample><programlisting>
|
which will look up the type information
|
||||||
GTypeInstance* g_type_create_instance (GType type);
|
structure associated with the type requested. Then, the instance size and instantiation
|
||||||
void g_type_free_instance (GTypeInstance *instance);
|
policy (if the <structfield>n_preallocs</structfield> field is set
|
||||||
</programlisting></informalexample>
|
to a non-zero value, the type system allocates
|
||||||
<function><link linkend="g-type-create-instance">g_type_create_instance</link></function> will look up the type information
|
|
||||||
structure associated to the type requested. Then, the instance size and instantiation
|
|
||||||
policy (if the n_preallocs field is set to a non-zero value, the type system allocates
|
|
||||||
the object's instance structures in chunks rather than mallocing for every instance)
|
the object's instance structures in chunks rather than mallocing for every instance)
|
||||||
declared by the user are used to get a buffer to hold the object's instance
|
declared by the user are used to get a buffer to hold the object's instance
|
||||||
structure.
|
structure.
|
||||||
@ -551,8 +517,9 @@ void g_type_free_instance (GTypeInstance *instance);
|
|||||||
class structure (ie: the embedded parent class structure) is initialized by copying the contents from
|
class structure (ie: the embedded parent class structure) is initialized by copying the contents from
|
||||||
the class structure of the parent class. The rest of class structure is initialized to zero. If there
|
the class structure of the parent class. The rest of class structure is initialized to zero. If there
|
||||||
is no parent, the entire class structure is initialized to zero. The type system then invokes the
|
is no parent, the entire class structure is initialized to zero. The type system then invokes the
|
||||||
base_class_initialization functions (<link linkend="GBaseInitFunc"><type>GBaseInitFunc</type></link>) from topmost
|
<function>base_class_initialization</function> functions
|
||||||
fundamental object to bottom-most most derived object. The object's class_init
|
(<link linkend="GBaseInitFunc"><type>GBaseInitFunc</type></link>) from topmost
|
||||||
|
fundamental object to bottom-most most derived object. The object's <function>class_init</function>
|
||||||
(<link linkend="GClassInitFunc"><type>GClassInitFunc</type></link>) function is invoked afterwards to complete
|
(<link linkend="GClassInitFunc"><type>GClassInitFunc</type></link>) function is invoked afterwards to complete
|
||||||
initialization of the class structure.
|
initialization of the class structure.
|
||||||
Finally, the object's interfaces are initialized (we will discuss interface initialization
|
Finally, the object's interfaces are initialized (we will discuss interface initialization
|
||||||
@ -562,8 +529,10 @@ void g_type_free_instance (GTypeInstance *instance);
|
|||||||
<para>
|
<para>
|
||||||
Once the type system has a pointer to an initialized class structure, it sets the object's
|
Once the type system has a pointer to an initialized class structure, it sets the object's
|
||||||
instance class pointer to the object's class structure and invokes the object's
|
instance class pointer to the object's class structure and invokes the object's
|
||||||
instance_init (<link linkend="GInstanceInitFunc"><type>GInstanceInitFunc</type></link>)functions, from top-most fundamental
|
<function>instance_init</function>
|
||||||
type to bottom-most most derived type.
|
(<link linkend="GInstanceInitFunc"><type>GInstanceInitFunc</type></link>)
|
||||||
|
functions, from top-most fundamental
|
||||||
|
type to bottom-most most-derived type.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -585,15 +554,15 @@ void g_type_free_instance (GTypeInstance *instance);
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
As many readers have now understood it, the base initialization/finalization process is
|
The base initialization/finalization process is
|
||||||
very similar to the C++ constructor/destructor paradigm. The practical details are different
|
very similar to the C++ constructor/destructor paradigm. The practical details are different
|
||||||
though and it is important not to get confused by superficial similarities.
|
though and it is important not to get confused by superficial similarities.
|
||||||
GTypes have no instance destruction mechanism. It is
|
GTypes have no instance destruction mechanism. It is
|
||||||
the user's responsibility to implement correct destruction semantics on top
|
the user's responsibility to implement correct destruction semantics on top
|
||||||
of the existing GType code. (this is what GObject does. See
|
of the existing GType code. (This is what GObject does: see
|
||||||
<xref linkend="chapter-gobject"/>)
|
<xref linkend="chapter-gobject"/>.)
|
||||||
Furthermore, C++ code equivalent to the base_init
|
Furthermore, C++ code equivalent to the <function>base_init</function>
|
||||||
and class_init callbacks of GType is usually not needed because C++ cannot really create object
|
and <function>class_init</function> callbacks of GType is usually not needed because C++ cannot really create object
|
||||||
types at runtime.
|
types at runtime.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@ -609,20 +578,20 @@ void g_type_free_instance (GTypeInstance *instance);
|
|||||||
<thead>
|
<thead>
|
||||||
<row>
|
<row>
|
||||||
<entry>Invocation time</entry>
|
<entry>Invocation time</entry>
|
||||||
<entry>Function Invoked</entry>
|
<entry>Function invoked</entry>
|
||||||
<entry>Function's parameters</entry>
|
<entry>Function's parameters</entry>
|
||||||
</row>
|
</row>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
<row>
|
||||||
<entry morerows="2">First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry>
|
<entry morerows="2">First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry>
|
||||||
<entry>type's base_init function</entry>
|
<entry>type's <function>base_init</function> function</entry>
|
||||||
<entry>On the inheritance tree of classes from fundamental type to target type.
|
<entry>On the inheritance tree of classes from fundamental type to target type.
|
||||||
base_init is invoked once for each class structure.</entry>
|
<function>base_init</function> is invoked once for each class structure.</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<!--entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry-->
|
<!--entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry-->
|
||||||
<entry>target type's class_init function</entry>
|
<entry>target type's <function>class_init</function> function</entry>
|
||||||
<entry>On target type's class structure</entry>
|
<entry>On target type's class structure</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
@ -633,7 +602,7 @@ void g_type_free_instance (GTypeInstance *instance);
|
|||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>Each call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry>
|
<entry>Each call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry>
|
||||||
<entry>target type's instance_init function</entry>
|
<entry>target type's <function>instance_init</function> function</entry>
|
||||||
<entry>On object's instance</entry>
|
<entry>On object's instance</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
@ -644,14 +613,14 @@ void g_type_free_instance (GTypeInstance *instance);
|
|||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for target type</entry-->
|
<!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for target type</entry-->
|
||||||
<entry>target type's class_finalize function</entry>
|
<entry>target type's <function>class_finalize</function> function</entry>
|
||||||
<entry>On target type's class structure</entry>
|
<entry>On target type's class structure</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for target type</entry-->
|
<!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for target type</entry-->
|
||||||
<entry>type's base_finalize function</entry>
|
<entry>type's <function>base_finalize</function> function</entry>
|
||||||
<entry>On the inheritance tree of classes from fundamental type to target type.
|
<entry>On the inheritance tree of classes from fundamental type to target type.
|
||||||
base_finalize is invoked once for each class structure.</entry>
|
<function>base_finalize</function> is invoked once for each class structure.</entry>
|
||||||
</row>
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
@ -674,7 +643,7 @@ void g_type_free_instance (GTypeInstance *instance);
|
|||||||
<para>
|
<para>
|
||||||
GType's interfaces are very similar to Java's interfaces. They allow
|
GType's interfaces are very similar to Java's interfaces. They allow
|
||||||
to describe a common API that several classes will adhere to.
|
to describe a common API that several classes will adhere to.
|
||||||
Imagine the play, pause and stop buttons on hi-fi equipment - those can
|
Imagine the play, pause and stop buttons on hi-fi equipment — those can
|
||||||
be seen as a playback interface. Once you know what they do, you can
|
be seen as a playback interface. Once you know what they do, you can
|
||||||
control your CD player, MP3 player or anything that uses these symbols.
|
control your CD player, MP3 player or anything that uses these symbols.
|
||||||
To declare an interface you have to register a non-instantiable
|
To declare an interface you have to register a non-instantiable
|
||||||
@ -708,8 +677,8 @@ void maman_ibaz_do_action (MamanIbaz *self)
|
|||||||
}
|
}
|
||||||
</programlisting></informalexample>
|
</programlisting></informalexample>
|
||||||
<function>maman_ibaz_get_type</function> registers a type named <emphasis>MamanIbaz</emphasis>
|
<function>maman_ibaz_get_type</function> registers a type named <emphasis>MamanIbaz</emphasis>
|
||||||
which inherits from G_TYPE_INTERFACE. All interfaces must be children of G_TYPE_INTERFACE in the
|
which inherits from <type>G_TYPE_INTERFACE</type>. All interfaces must
|
||||||
inheritance tree.
|
be children of <type>G_TYPE_INTERFACE</type> in the inheritance tree.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -717,7 +686,7 @@ void maman_ibaz_do_action (MamanIbaz *self)
|
|||||||
a <link linkend="GTypeInterface"><type>GTypeInterface</type></link> structure. The interface structure is expected to
|
a <link linkend="GTypeInterface"><type>GTypeInterface</type></link> structure. The interface structure is expected to
|
||||||
contain the function pointers of the interface methods. It is good style to
|
contain the function pointers of the interface methods. It is good style to
|
||||||
define helper functions for each of the interface methods which simply call
|
define helper functions for each of the interface methods which simply call
|
||||||
the interface' method directly: <function>maman_ibaz_do_action</function>
|
the interface's method directly: <function>maman_ibaz_do_action</function>
|
||||||
is one of these.
|
is one of these.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@ -829,10 +798,13 @@ G_DEFINE_TYPE_WITH_CODE (MamanBaz, maman_baz, G_TYPE_OBJECT,
|
|||||||
First a memory buffer is allocated to hold the interface structure. The parent's
|
First a memory buffer is allocated to hold the interface structure. The parent's
|
||||||
interface structure is then copied over to the new interface structure (the parent
|
interface structure is then copied over to the new interface structure (the parent
|
||||||
interface is already initialized at that point). If there is no parent interface,
|
interface is already initialized at that point). If there is no parent interface,
|
||||||
the interface structure is initialized with zeros. The g_type and the g_instance_type
|
the interface structure is initialized with zeros. The
|
||||||
fields are then initialized: g_type is set to the type of the most-derived interface
|
<structfield>g_type</structfield> and the
|
||||||
and g_instance_type is set to the type of the most derived type which implements
|
<structfield>g_instance_type</structfield> fields are then
|
||||||
this interface.
|
initialized: <structfield>g_type</structfield> is set to the type of
|
||||||
|
the most-derived interface and
|
||||||
|
<structfield>g_instance_type</structfield> is set to the type of the
|
||||||
|
most derived type which implements this interface.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -900,9 +872,7 @@ maman_ibaz_default_init (MamanIbazInterface *iface)
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If you have found the stuff about interface hairy, you are right: it is hairy but
|
In summary, interface initialization uses the following functions:
|
||||||
there is not much I can do about it. What I can do is summarize what you need to know
|
|
||||||
about interfaces:
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -953,9 +923,6 @@ maman_ibaz_default_init (MamanIbazInterface *iface)
|
|||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</table>
|
</table>
|
||||||
It is highly unlikely (i.e. I do not know of <emphasis>anyone</emphasis> who actually
|
|
||||||
used it) you will ever need other more fancy things such as the ones described in the
|
|
||||||
following section (<xref linkend="gtype-non-instantiable-classed-dest"/>).
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
@ -1007,15 +974,15 @@ maman_ibaz_default_init (MamanIbazInterface *iface)
|
|||||||
<entry morerows="1">Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for type
|
<entry morerows="1">Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for type
|
||||||
implementing interface
|
implementing interface
|
||||||
</entry>
|
</entry>
|
||||||
<entry>interface' interface_finalize function</entry>
|
<entry>interface's <function>interface_finalize</function> function</entry>
|
||||||
<entry>On interface' vtable</entry>
|
<entry>On interface's vtable</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function>for type
|
<!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function>for type
|
||||||
implementing interface
|
implementing interface
|
||||||
</entry-->
|
</entry-->
|
||||||
<entry>interface' base_finalize function</entry>
|
<entry>interface's <function>base_finalize</function> function</entry>
|
||||||
<entry>On interface' vtable</entry>
|
<entry>On interface's vtable</entry>
|
||||||
</row>
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
<title>Data types and programming</title>
|
<title>Data types and programming</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
One could say (I have seen such definitions used in some textbooks on programming language theory)
|
One could say
|
||||||
that a programming language is merely a way to create data types and manipulate them. Most languages
|
that a programming language is merely a way to create data types and manipulate them. Most languages
|
||||||
provide a number of language-native types and a few primitives to create more complex types based
|
provide a number of language-native types and a few primitives to create more complex types based
|
||||||
on these primitive types.
|
on these primitive types.
|
||||||
@ -44,7 +44,7 @@
|
|||||||
In C, the language provides types such as <emphasis>char</emphasis>, <emphasis>long</emphasis>,
|
In C, the language provides types such as <emphasis>char</emphasis>, <emphasis>long</emphasis>,
|
||||||
<emphasis>pointer</emphasis>. During compilation of C code, the compiler maps these
|
<emphasis>pointer</emphasis>. During compilation of C code, the compiler maps these
|
||||||
language types to the compiler's target architecture machine types. If you are using a C interpreter
|
language types to the compiler's target architecture machine types. If you are using a C interpreter
|
||||||
(I have never seen one myself but it is possible :), the interpreter (the program which interprets
|
(assuming one exists), the interpreter (the program which interprets
|
||||||
the source code and executes it) maps the language types to the machine types of the target machine at
|
the source code and executes it) maps the language types to the machine types of the target machine at
|
||||||
runtime, during the program execution (or just before execution if it uses a Just In Time compiler engine).
|
runtime, during the program execution (or just before execution if it uses a Just In Time compiler engine).
|
||||||
</para>
|
</para>
|
||||||
@ -87,14 +87,17 @@ print "this is an integer converted to a string:" . $tmp . "\n";
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
For the sake of discussion, here is a sample C function and the associated 32 bit x86
|
For the sake of discussion, here is a sample C function and the associated 32 bit x86
|
||||||
assembly code generated by GCC on my Linux box:
|
assembly code generated by GCC on a Linux computer:
|
||||||
<informalexample><programlisting>
|
<informalexample><programlisting>
|
||||||
static void function_foo (int foo)
|
static void
|
||||||
{}
|
function_foo (int foo)
|
||||||
|
|
||||||
int main (int argc, char *argv[])
|
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
function_foo (10);
|
function_foo (10);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -106,7 +109,7 @@ call 0x80482f4 <function_foo>
|
|||||||
The assembly code shown above is pretty straightforward: the first instruction pushes
|
The assembly code shown above is pretty straightforward: the first instruction pushes
|
||||||
the hexadecimal value 0xa (decimal value 10) as a 32-bit integer on the stack and calls
|
the hexadecimal value 0xa (decimal value 10) as a 32-bit integer on the stack and calls
|
||||||
<function>function_foo</function>. As you can see, C function calls are implemented by
|
<function>function_foo</function>. As you can see, C function calls are implemented by
|
||||||
gcc by native function calls (this is probably the fastest implementation possible).
|
GCC as native function calls (this is probably the fastest implementation possible).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user