nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | <?xml version='1.0' encoding="UTF-8"?> |
2 | <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" |
||
3 | "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ |
||
4 | ]> |
||
5 | <chapter id="chapter-gobject"> |
||
6 | <title>The GObject base class</title> |
||
7 | |||
8 | <para> |
||
9 | The previous chapter discussed the details of GLib's Dynamic Type System. |
||
10 | The GObject library also contains an implementation for a base fundamental |
||
11 | type named <link linkend="GObject"><type>GObject</type></link>. |
||
12 | </para> |
||
13 | |||
14 | <para> |
||
15 | <link linkend="GObject"><type>GObject</type></link> is a fundamental classed instantiable type. It implements: |
||
16 | <itemizedlist> |
||
17 | <listitem><para>Memory management with reference counting</para></listitem> |
||
18 | <listitem><para>Construction/Destruction of instances</para></listitem> |
||
19 | <listitem><para>Generic per-object properties with set/get function pairs</para></listitem> |
||
20 | <listitem><para>Easy use of signals</para></listitem> |
||
21 | </itemizedlist> |
||
22 | All the GNOME libraries which use the GLib type system (like GTK+ and GStreamer) |
||
23 | inherit from <link linkend="GObject"><type>GObject</type></link> which is why it is important to understand |
||
24 | the details of how it works. |
||
25 | </para> |
||
26 | |||
27 | <sect1 id="gobject-instantiation"> |
||
28 | <title>Object instantiation</title> |
||
29 | |||
30 | <para> |
||
31 | The <function><link linkend="g-object-new">g_object_new</link></function> |
||
32 | family of functions can be used to instantiate any GType which inherits |
||
33 | from the GObject base type. All these functions make sure the class and |
||
34 | instance structures have been correctly initialized by GLib's type system |
||
35 | and then invoke at one point or another the constructor class method |
||
36 | which is used to: |
||
37 | <itemizedlist> |
||
38 | <listitem><para> |
||
39 | Allocate and clear memory through <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>, |
||
40 | </para></listitem> |
||
41 | <listitem><para> |
||
42 | Initialize the object's instance with the construction properties. |
||
43 | </para></listitem> |
||
44 | </itemizedlist> |
||
45 | Although one can expect all class and instance members (except the fields |
||
46 | pointing to the parents) to be set to zero, some consider it good practice |
||
47 | to explicitly set them. |
||
48 | </para> |
||
49 | |||
50 | <para> |
||
51 | Once all construction operations have been completed and constructor |
||
52 | properties set, the constructed class method is called. |
||
53 | </para> |
||
54 | |||
55 | <para> |
||
56 | Objects which inherit from GObject are allowed to override this |
||
57 | constructed class method. |
||
58 | The example below shows how <type>ViewerFile</type> overrides the parent's construction process: |
||
59 | <informalexample><programlisting> |
||
60 | #define VIEWER_TYPE_FILE viewer_file_get_type () |
||
61 | G_DECLARE_FINAL_TYPE (ViewerFile, viewer_file, VIEWER, FILE, GObject) |
||
62 | |||
63 | struct _ViewerFile |
||
64 | { |
||
65 | GObject parent_instance; |
||
66 | |||
67 | /* instance members */ |
||
68 | }; |
||
69 | |||
70 | /* will create viewer_file_get_type and set viewer_file_parent_class */ |
||
71 | G_DEFINE_TYPE (ViewerFile, viewer_file, G_TYPE_OBJECT) |
||
72 | |||
73 | static void |
||
74 | viewer_file_constructed (GObject *obj) |
||
75 | { |
||
76 | /* update the object state depending on constructor properties */ |
||
77 | |||
78 | /* Always chain up to the parent constructed function to complete object |
||
79 | * initialisation. */ |
||
80 | G_OBJECT_CLASS (viewer_file_parent_class)->constructed (obj); |
||
81 | } |
||
82 | |||
83 | static void |
||
84 | viewer_file_class_init (ViewerFileClass *klass) |
||
85 | { |
||
86 | GObjectClass *object_class = G_OBJECT_CLASS (klass); |
||
87 | |||
88 | object_class->constructed = viewer_file_constructed; |
||
89 | } |
||
90 | |||
91 | static void |
||
92 | viewer_file_init (ViewerFile *self) |
||
93 | { |
||
94 | /* initialize the object */ |
||
95 | } |
||
96 | |||
97 | </programlisting></informalexample> |
||
98 | If the user instantiates an object <type>ViewerFile</type> with: |
||
99 | <informalexample><programlisting> |
||
100 | ViewerFile *file = g_object_new (VIEWER_TYPE_FILE, NULL); |
||
101 | </programlisting></informalexample> |
||
102 | If this is the first instantiation of such an object, the |
||
103 | <function>viewer_file_class_init</function> function will be invoked |
||
104 | after any <function>viewer_file_base_class_init</function> function. |
||
105 | This will make sure the class structure of this new object is |
||
106 | correctly initialized. Here, <function>viewer_file_class_init</function> |
||
107 | is expected to override the object's class methods and setup the |
||
108 | class' own methods. In the example above, the constructor method is |
||
109 | the only overridden method: it is set to |
||
110 | <function>viewer_file_constructor</function>. |
||
111 | </para> |
||
112 | |||
113 | <para> |
||
114 | Once <function><link linkend="g-object-new">g_object_new</link></function> has obtained a reference to an initialized |
||
115 | class structure, it invokes its constructor method to create an instance of the new |
||
116 | object, if the constructor has been overridden in <function>viewer_file_class_init</function>. |
||
117 | Overridden constructors must chain up to their parent’s constructor. In |
||
118 | order to find the parent class and chain up to the parent class |
||
119 | constructor, we can use the <literal>viewer_file_parent_class</literal> |
||
120 | pointer that has been set up for us by the |
||
121 | <link linkend="G-DEFINE-TYPE:CAPS"><literal>G_DEFINE_TYPE</literal></link> |
||
122 | macro. |
||
123 | </para> |
||
124 | |||
125 | <para> |
||
126 | Finally, at one point or another, <function>g_object_constructor</function> is invoked |
||
127 | by the last constructor in the chain. This function allocates the object's instance buffer |
||
128 | through <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> |
||
129 | which means that the <function>instance_init</function> function is invoked at this point if one |
||
130 | was registered. After <function>instance_init</function> returns, the object is fully initialized and should be |
||
131 | ready to have its methods called by the user. When |
||
132 | <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> |
||
133 | returns, <function>g_object_constructor</function> sets the construction properties |
||
134 | (i.e. the properties which were given to <function><link linkend="g-object-new">g_object_new</link></function>) and returns |
||
135 | to the user's constructor. |
||
136 | </para> |
||
137 | |||
138 | <para> |
||
139 | The process described above might seem a bit complicated, but it can be |
||
140 | summarized easily by the table below which lists the functions invoked |
||
141 | by <function><link linkend="g-object-new">g_object_new</link></function> |
||
142 | and their order of invocation: |
||
143 | </para> |
||
144 | |||
145 | <para> |
||
146 | <table id="gobject-construction-table"> |
||
147 | <title><function><link linkend="g-object-new">g_object_new</link></function></title> |
||
148 | <tgroup cols="3"> |
||
149 | <colspec colwidth="*" colnum="1" align="left"/> |
||
150 | <colspec colwidth="*" colnum="2" align="left"/> |
||
151 | <colspec colwidth="8*" colnum="3" align="left"/> |
||
152 | |||
153 | <thead> |
||
154 | <row> |
||
155 | <entry>Invocation time</entry> |
||
156 | <entry>Function invoked</entry> |
||
157 | <entry>Function's parameters</entry> |
||
158 | <entry>Remark</entry> |
||
159 | </row> |
||
160 | </thead> |
||
161 | <tbody> |
||
162 | <row> |
||
163 | <entry morerows="3">First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry> |
||
164 | <entry>target type's <function>base_init</function> function</entry> |
||
165 | <entry>On the inheritance tree of classes from fundamental type to target type. |
||
166 | <function>base_init</function> is invoked once for each class structure.</entry> |
||
167 | <entry>Never used in practice. Unlikely you will need it.</entry> |
||
168 | </row> |
||
169 | <row> |
||
170 | <!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry--> |
||
171 | <entry>target type's <function>class_init</function> function</entry> |
||
172 | <entry>On target type's class structure</entry> |
||
173 | <entry> |
||
174 | Here, you should make sure to initialize or override class methods (that is, |
||
175 | assign to each class' method its function pointer) and create the signals and |
||
176 | the properties associated to your object. |
||
177 | </entry> |
||
178 | </row> |
||
179 | <row> |
||
180 | <!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry--> |
||
181 | <entry>interface's <function>base_init</function> function</entry> |
||
182 | <entry>On interface's vtable</entry> |
||
183 | <entry></entry> |
||
184 | </row> |
||
185 | <row> |
||
186 | <!--entry>First call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry--> |
||
187 | <entry>interface's <function>interface_init</function> function</entry> |
||
188 | <entry>On interface's vtable</entry> |
||
189 | <entry></entry> |
||
190 | </row> |
||
191 | <row> |
||
192 | <entry morerows="2">Each call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry> |
||
193 | <entry>target type's class <function>constructor</function> method: <function>GObjectClass->constructor</function></entry> |
||
194 | <entry>On object's instance</entry> |
||
195 | <entry> |
||
196 | If you need to handle construct properties in a custom way, or implement a singleton class, override the constructor |
||
197 | method and make sure to chain up to the object's |
||
198 | parent class before doing your own initialization. |
||
199 | In doubt, do not override the constructor method. |
||
200 | </entry> |
||
201 | </row> |
||
202 | <row> |
||
203 | <!--entry>Each call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry--> |
||
204 | <entry>type's <function>instance_init</function> function</entry> |
||
205 | <entry>On the inheritance tree of classes from fundamental type to target type. |
||
206 | the <function>instance_init</function> provided for each type is invoked once for each instance |
||
207 | structure.</entry> |
||
208 | <entry> |
||
209 | Provide an <function>instance_init</function> function to initialize your object before its construction |
||
210 | properties are set. This is the preferred way to initialize a GObject instance. |
||
211 | This function is equivalent to C++ constructors. |
||
212 | </entry> |
||
213 | </row> |
||
214 | <row> |
||
215 | <!--entry>Each call to <function><link linkend="g-object-new">g_object_new</link></function> for target type</entry--> |
||
216 | <entry>target type's class <function>constructed</function> method: <function>GObjectClass->constructed</function></entry> |
||
217 | <entry>On object's instance</entry> |
||
218 | <entry> |
||
219 | If you need to perform object initialization steps after all construct properties have been set. |
||
220 | This is the final step in the object initialization process, and is only called if the <function>constructor</function> |
||
221 | method returned a new object instance (rather than, for example, an existing singleton). |
||
222 | </entry> |
||
223 | </row> |
||
224 | </tbody> |
||
225 | </tgroup> |
||
226 | </table> |
||
227 | </para> |
||
228 | |||
229 | <para> |
||
230 | Readers should feel concerned about one little twist in the order in |
||
231 | which functions are invoked: while, technically, the class' constructor |
||
232 | method is called <emphasis>before</emphasis> the GType's <function>instance_init</function> |
||
233 | function (since <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> which calls <function>instance_init</function> is called by |
||
234 | <function>g_object_constructor</function> which is the top-level class |
||
235 | constructor method and to which users are expected to chain to), the |
||
236 | user's code which runs in a user-provided constructor will always |
||
237 | run <emphasis>after</emphasis> GType's <function>instance_init</function> function since the |
||
238 | user-provided constructor <emphasis>must</emphasis> (you've been warned) |
||
239 | chain up <emphasis>before</emphasis> doing anything useful. |
||
240 | </para> |
||
241 | </sect1> |
||
242 | |||
243 | <sect1 id="gobject-memory"> |
||
244 | <title>Object memory management</title> |
||
245 | |||
246 | <para> |
||
247 | The memory-management API for GObjects is a bit complicated but the idea behind it |
||
248 | is pretty simple: the goal is to provide a flexible model based on reference counting |
||
249 | which can be integrated in applications which use or require different memory management |
||
250 | models (such as garbage collection). The methods which are used to |
||
251 | manipulate this reference count are described below. |
||
252 | </para> |
||
253 | |||
254 | <sect2 id="gobject-memory-refcount"> |
||
255 | <title>Reference count</title> |
||
256 | |||
257 | <para> |
||
258 | The functions <function><link linkend="g-object-ref">g_object_ref</link></function>/<function><link linkend="g-object-unref">g_object_unref</link></function> respectively |
||
259 | increase and decrease the reference count. These functions are |
||
260 | thread-safe. |
||
261 | <function><link linkend="g-clear-object">g_clear_object</link></function> |
||
262 | is a convenience wrapper around <function>g_object_unref</function> |
||
263 | which also clears the pointer passed to it. |
||
264 | </para> |
||
265 | <para> |
||
266 | The reference count is initialized to one by |
||
267 | <function><link linkend="g-object-new">g_object_new</link></function> which means that the caller |
||
268 | is currently the sole owner of the newly-created reference. |
||
269 | When the reference count reaches zero, that is, |
||
270 | when <function><link linkend="g-object-unref">g_object_unref</link></function> is called by the last client holding |
||
271 | a reference to the object, the <emphasis>dispose</emphasis> and the |
||
272 | <emphasis>finalize</emphasis> class methods are invoked. |
||
273 | </para> |
||
274 | <para> |
||
275 | Finally, after <emphasis>finalize</emphasis> is invoked, |
||
276 | <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> is called to free the object instance. |
||
277 | Depending on the memory allocation policy decided when the type was registered (through |
||
278 | one of the <function>g_type_register_*</function> functions), the object's instance |
||
279 | memory will be freed or returned to the object pool for this type. |
||
280 | Once the object has been freed, if it was the last instance of the type, the type's class |
||
281 | will be destroyed as described in <xref linkend="gtype-instantiable-classed"/> and |
||
282 | <xref linkend="gtype-non-instantiable-classed"/>. |
||
283 | </para> |
||
284 | |||
285 | <para> |
||
286 | The table below summarizes the destruction process of a GObject: |
||
287 | <table id="gobject-destruction-table"> |
||
288 | <title><function><link linkend="g-object-unref">g_object_unref</link></function></title> |
||
289 | <tgroup cols="3"> |
||
290 | <colspec colwidth="*" colnum="1" align="left"/> |
||
291 | <colspec colwidth="*" colnum="2" align="left"/> |
||
292 | <colspec colwidth="8*" colnum="3" align="left"/> |
||
293 | |||
294 | <thead> |
||
295 | <row> |
||
296 | <entry>Invocation time</entry> |
||
297 | <entry>Function invoked</entry> |
||
298 | <entry>Function's parameters</entry> |
||
299 | <entry>Remark</entry> |
||
300 | </row> |
||
301 | </thead> |
||
302 | <tbody> |
||
303 | <row> |
||
304 | <entry morerows="1">Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for an instance |
||
305 | of target type |
||
306 | </entry> |
||
307 | <entry>target type's dispose class function</entry> |
||
308 | <entry>GObject instance</entry> |
||
309 | <entry> |
||
310 | When dispose ends, the object should not hold any reference to any other |
||
311 | member object. The object is also expected to be able to answer client |
||
312 | method invocations (with possibly an error code but no memory violation) |
||
313 | until finalize is executed. dispose can be executed more than once. |
||
314 | dispose should chain up to its parent implementation just before returning |
||
315 | to the caller. |
||
316 | </entry> |
||
317 | </row> |
||
318 | <row> |
||
319 | <!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for an instance |
||
320 | of target type |
||
321 | </entry--> |
||
322 | <entry>target type's finalize class function</entry> |
||
323 | <entry>GObject instance</entry> |
||
324 | <entry> |
||
325 | Finalize is expected to complete the destruction process initiated by |
||
326 | dispose. It should complete the object's destruction. finalize will be |
||
327 | executed only once. |
||
328 | finalize should chain up to its parent implementation just before returning |
||
329 | to the caller. |
||
330 | The reason why the destruction process is split is two different phases is |
||
331 | explained in <xref linkend="gobject-memory-cycles"/>. |
||
332 | </entry> |
||
333 | </row> |
||
334 | <row> |
||
335 | <entry morerows="3">Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last |
||
336 | instance of target type |
||
337 | </entry> |
||
338 | <entry>interface's <function>interface_finalize</function> function</entry> |
||
339 | <entry>On interface's vtable</entry> |
||
340 | <entry>Never used in practice. Unlikely you will need it.</entry> |
||
341 | </row> |
||
342 | <row> |
||
343 | <!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function>for the last |
||
344 | instance of target type |
||
345 | </entry--> |
||
346 | <entry>interface's <function>base_finalize</function> function</entry> |
||
347 | <entry>On interface's vtable</entry> |
||
348 | <entry>Never used in practice. Unlikely you will need it.</entry> |
||
349 | </row> |
||
350 | <row> |
||
351 | <!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last |
||
352 | instance of target type |
||
353 | </entry--> |
||
354 | <entry>target type's <function>class_finalize</function> function</entry> |
||
355 | <entry>On target type's class structure</entry> |
||
356 | <entry>Never used in practice. Unlikely you will need it.</entry> |
||
357 | </row> |
||
358 | <row> |
||
359 | <!--entry>Last call to <function><link linkend="g-object-unref">g_object_unref</link></function> for the last |
||
360 | instance of target type |
||
361 | </entry--> |
||
362 | <entry>type's <function>base_finalize</function> function</entry> |
||
363 | <entry>On the inheritance tree of classes from fundamental type to target type. |
||
364 | <function>base_init</function> is invoked once for each class structure.</entry> |
||
365 | <entry>Never used in practice. Unlikely you will need it.</entry> |
||
366 | </row> |
||
367 | </tbody> |
||
368 | </tgroup> |
||
369 | </table> |
||
370 | </para> |
||
371 | |||
372 | </sect2> |
||
373 | |||
374 | <sect2 id="gobject-memory-weakref"> |
||
375 | <title>Weak References</title> |
||
376 | |||
377 | <para> |
||
378 | Weak references are used to monitor object finalization: |
||
379 | <function><link linkend="g-object-weak-ref">g_object_weak_ref</link></function> adds a monitoring callback which does |
||
380 | not hold a reference to the object but which is invoked when the object runs |
||
381 | its dispose method. As such, each weak ref can be invoked more than once upon |
||
382 | object finalization (since dispose can run more than once during object |
||
383 | finalization). |
||
384 | </para> |
||
385 | |||
386 | <para> |
||
387 | <function><link linkend="g-object-weak-unref">g_object_weak_unref</link></function> can be used to remove a monitoring |
||
388 | callback from the object. |
||
389 | </para> |
||
390 | |||
391 | <para> |
||
392 | Weak references are also used to implement <function><link linkend="g-object-add-weak-pointer">g_object_add_weak_pointer</link></function> |
||
393 | and <function><link linkend="g-object-remove-weak-pointer">g_object_remove_weak_pointer</link></function>. These functions add a weak reference |
||
394 | to the object they are applied to which makes sure to nullify the pointer given by the user |
||
395 | when object is finalized. |
||
396 | </para> |
||
397 | |||
398 | <para> |
||
399 | Similarly, <link linkend="GWeakRef"><type>GWeakRef</type></link> can be |
||
400 | used to implement weak references if thread safety is required. |
||
401 | </para> |
||
402 | </sect2> |
||
403 | |||
404 | <sect2 id="gobject-memory-cycles"> |
||
405 | <title>Reference counts and cycles</title> |
||
406 | |||
407 | <para> |
||
408 | GObject's memory management model was designed to be easily integrated in existing code |
||
409 | using garbage collection. This is why the destruction process is split in two phases: |
||
410 | the first phase, executed in the dispose handler is supposed to release all references |
||
411 | to other member objects. The second phase, executed by the finalize handler is supposed |
||
412 | to complete the object's destruction process. Object methods should be able to run |
||
413 | without program error in-between the two phases. |
||
414 | </para> |
||
415 | |||
416 | <para> |
||
417 | This two-step destruction process is very useful to break reference counting cycles. |
||
418 | While the detection of the cycles is up to the external code, once the cycles have been |
||
419 | detected, the external code can invoke <function><link linkend="g-object-run-dispose">g_object_run_dispose</link></function> which |
||
420 | will indeed break any existing cycles since it will run the dispose handler associated |
||
421 | to the object and thus release all references to other objects. |
||
422 | </para> |
||
423 | |||
424 | <para> |
||
425 | This explains one of the rules about the dispose handler stated earlier: |
||
426 | the dispose handler can be invoked multiple times. Let's say we |
||
427 | have a reference count cycle: object A references B which itself references object A. |
||
428 | Let's say we have detected the cycle and we want to destroy the two objects. One way to |
||
429 | do this would be to invoke <function><link linkend="g-object-run-dispose">g_object_run_dispose</link></function> on one of the |
||
430 | objects. |
||
431 | </para> |
||
432 | |||
433 | <para> |
||
434 | If object A releases all its references to all objects, this means it releases its |
||
435 | reference to object B. If object B was not owned by anyone else, this is its last |
||
436 | reference count which means this last unref runs B's dispose handler which, in turn, |
||
437 | releases B's reference on object A. If this is A's last reference count, this last |
||
438 | unref runs A's dispose handler which is running for the second time before |
||
439 | A's finalize handler is invoked ! |
||
440 | </para> |
||
441 | |||
442 | <para> |
||
443 | The above example, which might seem a bit contrived, can really happen if |
||
444 | GObjects are being handled by language bindings — hence the rules for |
||
445 | object destruction should be closely followed. |
||
446 | </para> |
||
447 | </sect2> |
||
448 | </sect1> |
||
449 | |||
450 | <sect1 id="gobject-properties"> |
||
451 | <title>Object properties</title> |
||
452 | |||
453 | <para> |
||
454 | One of GObject's nice features is its generic get/set mechanism for object |
||
455 | properties. When an object |
||
456 | is instantiated, the object's <function>class_init</function> handler should be used to register |
||
457 | the object's properties with <function><link linkend="g-object-class-install-properties">g_object_class_install_properties</link></function>. |
||
458 | </para> |
||
459 | |||
460 | <para> |
||
461 | The best way to understand how object properties work is by looking at a real example |
||
462 | of how it is used: |
||
463 | <informalexample><programlisting> |
||
464 | /************************************************/ |
||
465 | /* Implementation */ |
||
466 | /************************************************/ |
||
467 | |||
468 | enum |
||
469 | { |
||
470 | PROP_FILENAME = 1, |
||
471 | PROP_ZOOM_LEVEL, |
||
472 | N_PROPERTIES |
||
473 | }; |
||
474 | |||
475 | static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, }; |
||
476 | |||
477 | static void |
||
478 | viewer_file_set_property (GObject *object, |
||
479 | guint property_id, |
||
480 | const GValue *value, |
||
481 | GParamSpec *pspec) |
||
482 | { |
||
483 | ViewerFile *self = VIEWER_FILE (object); |
||
484 | |||
485 | switch (property_id) |
||
486 | { |
||
487 | case PROP_FILENAME: |
||
488 | g_free (self->priv->filename); |
||
489 | self->priv->filename = g_value_dup_string (value); |
||
490 | g_print ("filename: %s\n", self->priv->filename); |
||
491 | break; |
||
492 | |||
493 | case PROP_ZOOM_LEVEL: |
||
494 | self->priv->zoom_level = g_value_get_uint (value); |
||
495 | g_print ("zoom level: %u\n", self->priv->zoom_level); |
||
496 | break; |
||
497 | |||
498 | default: |
||
499 | /* We don't have any other property... */ |
||
500 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
||
501 | break; |
||
502 | } |
||
503 | } |
||
504 | |||
505 | static void |
||
506 | viewer_file_get_property (GObject *object, |
||
507 | guint property_id, |
||
508 | GValue *value, |
||
509 | GParamSpec *pspec) |
||
510 | { |
||
511 | ViewerFile *self = VIEWER_FILE (object); |
||
512 | |||
513 | switch (property_id) |
||
514 | { |
||
515 | case PROP_FILENAME: |
||
516 | g_value_set_string (value, self->priv->filename); |
||
517 | break; |
||
518 | |||
519 | case PROP_ZOOM_LEVEL: |
||
520 | g_value_set_uint (value, self->priv->zoom_level); |
||
521 | break; |
||
522 | |||
523 | default: |
||
524 | /* We don't have any other property... */ |
||
525 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
||
526 | break; |
||
527 | } |
||
528 | } |
||
529 | |||
530 | static void |
||
531 | viewer_file_class_init (ViewerFileClass *klass) |
||
532 | { |
||
533 | GObjectClass *object_class = G_OBJECT_CLASS (klass); |
||
534 | |||
535 | object_class->set_property = viewer_file_set_property; |
||
536 | object_class->get_property = viewer_file_get_property; |
||
537 | |||
538 | obj_properties[PROP_FILENAME] = |
||
539 | g_param_spec_string ("filename", |
||
540 | "Filename", |
||
541 | "Name of the file to load and display from.", |
||
542 | NULL /* default value */, |
||
543 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); |
||
544 | |||
545 | obj_properties[PROP_ZOOM_LEVEL] = |
||
546 | g_param_spec_uint ("zoom-level", |
||
547 | "Zoom level", |
||
548 | "Zoom level to view the file at.", |
||
549 | |||
550 | 10 /* maximum value */, |
||
551 | 2 /* default value */, |
||
552 | G_PARAM_READWRITE)); |
||
553 | |||
554 | g_object_class_install_properties (object_class, |
||
555 | N_PROPERTIES, |
||
556 | obj_properties); |
||
557 | } |
||
558 | |||
559 | /************************************************/ |
||
560 | /* Use */ |
||
561 | /************************************************/ |
||
562 | |||
563 | ViewerFile *file; |
||
564 | GValue val = G_VALUE_INIT; |
||
565 | |||
566 | file = g_object_new (VIEWER_TYPE_FILE, NULL); |
||
567 | |||
568 | g_value_init (&val, G_TYPE_UINT); |
||
569 | g_value_set_char (&val, 11); |
||
570 | |||
571 | g_object_set_property (G_OBJECT (file), "zoom-level", &val); |
||
572 | |||
573 | g_value_unset (&val); |
||
574 | </programlisting></informalexample> |
||
575 | The client code above looks simple but a lot of things happen under the hood: |
||
576 | </para> |
||
577 | |||
578 | <para> |
||
579 | <function><link linkend="g-object-set-property">g_object_set_property</link></function> first ensures a property |
||
580 | with this name was registered in <emphasis>file</emphasis>'s <function>class_init</function> handler. If so it walks the class hierarchy, |
||
581 | from bottom-most most-derived type, to top-most fundamental type to find the class |
||
582 | which registered that property. It then tries to convert the user-provided |
||
583 | <link linkend="GValue"><type>GValue</type></link> |
||
584 | into a <type>GValue</type> whose type is that of the associated property. |
||
585 | </para> |
||
586 | |||
587 | <para> |
||
588 | If the user provides a <type>signed char</type> <type>GValue</type>, as is shown |
||
589 | here, and if the object's property was registered as an <type>unsigned int</type>, |
||
590 | <function><link linkend="g-value-transform">g_value_transform</link></function> will try to transform the input signed char into |
||
591 | an unsigned int. Of course, the success of the transformation depends on the availability |
||
592 | of the required transform function. In practice, there will almost always be a transformation |
||
593 | <footnote> |
||
594 | <para>Its behaviour might not be what you expect but it is up to you to actually avoid |
||
595 | relying on these transformations. |
||
596 | </para> |
||
597 | </footnote> |
||
598 | which matches and conversion will be carried out if needed. |
||
599 | </para> |
||
600 | |||
601 | <para> |
||
602 | After transformation, the <link linkend="GValue"><type>GValue</type></link> is validated by |
||
603 | <function><link linkend="g-param-value-validate">g_param_value_validate</link></function> which makes sure the user's |
||
604 | data stored in the <link linkend="GValue"><type>GValue</type></link> matches the characteristics specified by |
||
605 | the property's <link linkend="GParamSpec"><type>GParamSpec</type></link>. |
||
606 | Here, the <link linkend="GParamSpec"><type>GParamSpec</type></link> we |
||
607 | provided in <function>class_init</function> has a validation function which makes sure that the GValue |
||
608 | contains a value which respects the minimum and maximum bounds of the |
||
609 | <link linkend="GParamSpec"><type>GParamSpec</type></link>. In the example above, the client's GValue does not |
||
610 | respect these constraints (it is set to 11, while the maximum is 10). As such, the |
||
611 | <function><link linkend="g-object-set-property">g_object_set_property</link></function> function will return with an error. |
||
612 | </para> |
||
613 | |||
614 | <para> |
||
615 | 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> |
||
616 | would have proceeded with calling the object's |
||
617 | <function>set_property</function> class method. Here, since our |
||
618 | implementation of <type>ViewerFile</type> did override this method, execution would jump to |
||
619 | <function>viewer_file_set_property</function> after having retrieved from the |
||
620 | <link linkend="GParamSpec"><type>GParamSpec</type></link> the <emphasis>param_id</emphasis> |
||
621 | <footnote> |
||
622 | <para> |
||
623 | It should be noted that the param_id used here need only to uniquely identify each |
||
624 | <link linkend="GParamSpec"><type>GParamSpec</type></link> within the <type>ViewerFileClass</type> such that the switch |
||
625 | used in the set and get methods actually works. Of course, this locally-unique |
||
626 | integer is purely an optimization: it would have been possible to use a set of |
||
627 | <emphasis>if (strcmp (a, b) == 0) {} else if (strcmp (a, b) == 0) {}</emphasis> statements. |
||
628 | </para> |
||
629 | </footnote> |
||
630 | which had been stored by |
||
631 | <function><link linkend="g-object-class-install-property">g_object_class_install_property</link></function>. |
||
632 | </para> |
||
633 | |||
634 | <para> |
||
635 | Once the property has been set by the object's |
||
636 | <function>set_property</function> class method, execution |
||
637 | returns to <function><link linkend="g-object-set-property">g_object_set_property</link></function> which makes sure that |
||
638 | the "notify" signal is emitted on the object's instance with the changed property as |
||
639 | parameter unless notifications were frozen by <function><link linkend="g-object-freeze-notify">g_object_freeze_notify</link></function>. |
||
640 | </para> |
||
641 | |||
642 | <para> |
||
643 | <function><link linkend="g-object-thaw-notify">g_object_thaw_notify</link></function> can be used to re-enable notification of |
||
644 | property modifications through the |
||
645 | <link linkend="GObject-notify"><type>“notify”</type></link> signal. It is important to remember that |
||
646 | even if properties are changed while property change notification is frozen, the "notify" |
||
647 | signal will be emitted once for each of these changed properties as soon as the property |
||
648 | change notification is thawed: no property change is lost for the "notify" |
||
649 | signal, although multiple notifications for a single property are |
||
650 | compressed. Signals can only be delayed by the notification freezing |
||
651 | mechanism. |
||
652 | </para> |
||
653 | |||
654 | <para> |
||
655 | It sounds like a tedious task to set up GValues every time when one wants to modify a property. |
||
656 | In practice one will rarely do this. The functions <function><link linkend="g-object-set-property">g_object_set_property</link></function> |
||
657 | and <function><link linkend="g-object-get-property">g_object_get_property</link></function> |
||
658 | are meant to be used by language bindings. For application there is an easier way and |
||
659 | that is described next. |
||
660 | </para> |
||
661 | |||
662 | <sect2 id="gobject-multi-properties"> |
||
663 | <title>Accessing multiple properties at once</title> |
||
664 | |||
665 | <para> |
||
666 | It is interesting to note that the <function><link linkend="g-object-set">g_object_set</link></function> and |
||
667 | <function><link linkend="g-object-set-valist">g_object_set_valist</link></function> (variadic version) functions can be used to set |
||
668 | multiple properties at once. The client code shown above can then be re-written as: |
||
669 | <informalexample><programlisting> |
||
670 | ViewerFile *file; |
||
671 | file = /* */; |
||
672 | g_object_set (G_OBJECT (file), |
||
673 | "zoom-level", 6, |
||
674 | "filename", "~/some-file.txt", |
||
675 | NULL); |
||
676 | </programlisting></informalexample> |
||
677 | This saves us from managing the GValues that we were needing to handle when using |
||
678 | <function><link linkend="g-object-set-property">g_object_set_property</link></function>. |
||
679 | The code above will trigger one notify signal emission for each property modified. |
||
680 | </para> |
||
681 | |||
682 | <para> |
||
683 | Equivalent <function>_get</function> versions are also available: |
||
684 | <function><link linkend="g-object-get">g_object_get</link></function> |
||
685 | and <function><link linkend="g-object-get-valist">g_object_get_valist</link></function> (variadic version) can be used to get numerous |
||
686 | properties at once. |
||
687 | </para> |
||
688 | |||
689 | <para> |
||
690 | These high level functions have one drawback — they don't provide a return value. |
||
691 | One should pay attention to the argument types and ranges when using them. |
||
692 | A known source of errors is to pass a different type from what the |
||
693 | property expects; for instance, passing an integer when the property |
||
694 | expects a floating point value and thus shifting all subsequent parameters |
||
695 | by some number of bytes. Also forgetting the terminating |
||
696 | <literal>NULL</literal> will lead to undefined behaviour. |
||
697 | </para> |
||
698 | |||
699 | <para> |
||
700 | This explains how <function><link linkend="g-object-new">g_object_new</link></function>, |
||
701 | <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> |
||
702 | work: they parse the user-provided variable number of parameters and invoke |
||
703 | <function><link linkend="g-object-set">g_object_set</link></function> on the parameters only after the object has been successfully constructed. |
||
704 | The "notify" signal will be emitted for each property set. |
||
705 | </para> |
||
706 | |||
707 | </sect2> |
||
708 | |||
709 | <!-- @todo tell here about how to pass use handle properties in derived classes --> |
||
710 | |||
711 | </sect1> |
||
712 | |||
713 | </chapter> |