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