<para>
The two previous chapters discussed the details of GLib's Dynamic Type System
and its signal control system. The GObject library also contains an implementation
- for a base fundamental type named <type><link linkend="GObject">GObject</link></type>.
+ for a base fundamental type named <link linkend="GObject"><type>GObject</type></link>.
</para>
<para>
- <type><link linkend="GObject">GObject</link></type> is a fundamental classed instantiable type. It implements:
+ <link linkend="GObject"><type>GObject</type></link> is a fundamental classed instantiable type. It implements:
<itemizedlist>
<listitem><para>Memory management with reference counting</para></listitem>
<listitem><para>Construction/Destruction of instances</para></listitem>
<listitem><para>Easy use of signals</para></listitem>
</itemizedlist>
All the GNOME libraries which use the GLib type system (like GTK+ and GStreamer)
- inherit from <type><link linkend="GObject">GObject</link></type> which is why it is important to understand
+ inherit from <link linkend="GObject"><type>GObject</type></link> which is why it is important to understand
the details of how it works.
</para>
{
/* Always chain up to the parent constructor */
- MamanBarClass *klass;
- GObjectClass *parent_class;
- parent_class = G_OBJECT_CLASS (maman_bar_parent_class);
- obj = parent_class->constructor (gtype, n_properties, properties);
+ obj = G_OBJECT_CLASS (maman_bar_parent_class)->constructor (gtype, n_properties, properties);
}
/* update the object state depending on constructor properties */
<para>
This two-step destruction process is very useful to break reference counting cycles.
While the detection of the cycles is up to the external code, once the cycles have been
- detected, the external code can invoke <function><link linkend="g-object-dispose">g_object_dispose</link></function> which
+ detected, the external code can invoke <function><link linkend="g-object-run-dispose">g_object_run_dispose</link></function> which
will indeed break any existing cycles since it will run the dispose handler associated
to the object and thus release all references to other objects.
</para>
we stated a bit sooner: the dispose handler can be invoked multiple times. Let's say we
have a reference count cycle: object A references B which itself references object A.
Let's say we have detected the cycle and we want to destroy the two objects. One way to
- do this would be to invoke <function><link linkend="g-object-dispose">g_object_dispose</link></function> on one of the
+ do this would be to invoke <function><link linkend="g-object-run-dispose">g_object_run_dispose</link></function> on one of the
objects.
</para>
One of GObject's nice features is its generic get/set mechanism for object
properties. When an object
is instantiated, the object's class_init handler should be used to register
- the object's properties with <function><link linkend="g-object-class-install-property">g_object_class_install_property</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>
The best way to understand how object properties work is by looking at a real example
on how it is used:
-<programlisting>
+<informalexample><programlisting>
/************************************************/
/* Implementation */
/************************************************/
PROP_0,
PROP_MAMAN_NAME,
- PROP_PAPA_NUMBER
+ PROP_PAPA_NUMBER,
+
+ N_PROPERTIES
};
+static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
+
static void
maman_bar_set_property (GObject *object,
guint property_id,
maman_bar_class_init (MamanBarClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GParamSpec *pspec;
gobject_class->set_property = maman_bar_set_property;
gobject_class->get_property = maman_bar_get_property;
- pspec = g_param_spec_string ("maman-name",
- "Maman construct prop",
- "Set maman's name",
- "no-name-set" /* default value */,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
- g_object_class_install_property (gobject_class,
- PROP_MAMAN_NAME,
- pspec);
-
- pspec = g_param_spec_uchar ("papa-number",
- "Number of current Papa",
- "Set/Get papa's number",
- 0 /* minimum value */,
- 10 /* maximum value */,
- 2 /* default value */,
- G_PARAM_READWRITE);
- g_object_class_install_property (gobject_class,
- PROP_PAPA_NUMBER,
- pspec);
+ obj_properties[PROP_NAME] =
+ g_param_spec_string ("maman-name",
+ "Maman construct prop",
+ "Set maman's name",
+ "no-name-set" /* default value */,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+
+ obj_properties[PROP_NUMBER] =
+ g_param_spec_uchar ("papa-number",
+ "Number of current Papa",
+ "Set/Get papa's number",
+ 0 /* minimum value */,
+ 10 /* maximum value */,
+ 2 /* default value */,
+ G_PARAM_READWRITE);
+
+ g_object_class_install_properties (gobject_class,
+ N_PROPERTIES,
+ obj_properties);
}
/************************************************/
/************************************************/
GObject *bar;
-GValue val = { 0, };
+GValue val = G_VALUE_INIT;
bar = g_object_new (MAMAN_TYPE_SUBBAR, NULL);
g_object_set_property (G_OBJECT (bar), "papa-number", &val);
g_value_unset (&val);
-</programlisting>
+</programlisting></informalexample>
The client code just above looks simple but a lot of things happen under the hood:
</para>
<para>
<function><link linkend="g-object-set-property">g_object_set_property</link></function> first ensures a property
- with this name was registered in bar's class_init handler. If so, it calls
- <function><link linkend="object-set-property">object_set_property</link></function> which first walks the class hierarchy,
+ with this name was registered in bar's class_init 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.
</para>
<para>
- After transformation, the <type><link linkend="GValue">GValue</link></type> is validated by
+ After transformation, the <link linkend="GValue"><type>GValue</type></link> is validated by
<function><link linkend="g-param-value-validate">g_param_value_validate</link></function> which makes sure the user's
- data stored in the <type><link linkend="GValue">GValue</link></type> matches the characteristics specified by
- the property's <type><link linkend="GParamSpec">GParamSpec</link></type>. Here, the <type><link linkend="GParamSpec">GParamSpec</link></type> we
+ data stored in the <link linkend="GValue"><type>GValue</type></link> matches the characteristics specified by
+ the property's <link linkend="GParamSpec"><type>GParamSpec</type></link>.
+ Here, the <link linkend="GParamSpec"><type>GParamSpec</type></link> we
provided in class_init has a validation function which makes sure that the GValue
contains a value which respects the minimum and maximum bounds of the
- <type><link linkend="GParamSpec">GParamSpec</link></type>. In the example above, the client's GValue does not
+ <link linkend="GParamSpec"><type>GParamSpec</type></link>. In the example above, the client's GValue does not
respect these constraints (it is set to 11, while the maximum is 10). As such, the
<function><link linkend="g-object-set-property">g_object_set_property</link></function> function will return with an error.
</para>
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
<function>foo_set_property</function> after having retrieved from the
- <type><link linkend="GParamSpec">GParamSpec</link></type> the <emphasis>param_id</emphasis>
+ <link linkend="GParamSpec"><type>GParamSpec</type></link> the <emphasis>param_id</emphasis>
<footnote>
<para>
It should be noted that the param_id used here need only to uniquely identify each
- <type><link linkend="GParamSpec">GParamSpec</link></type> within the <type><link linkend="FooClass">FooClass</link></type> such that the switch
+ <link linkend="GParamSpec"><type>GParamSpec</type></link> within the <type>FooClass</type> such that the switch
used in the set and get methods actually works. Of course, this locally-unique
integer is purely an optimization: it would have been possible to use a set of
<emphasis>if (strcmp (a, b) == 0) {} else if (strcmp (a, b) == 0) {}</emphasis> statements.
<para>
Once the property has been set by the object's set_property class method, the code path
- returns to <function><link linkend="g-object-set-property">g_object_set_property</link></function> which calls
- <function><link linkend="g-object-notify-queue-thaw">g_object_notify_queue_thaw</link></function>. This function 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
parameter unless notifications were frozen by <function><link linkend="g-object-freeze-notify">g_object_freeze_notify</link></function>.
</para>