+++ /dev/null
-<?xml version='1.0' encoding="ISO-8859-1"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
-]>
- <chapter id="chapter-gtype">
- <title>The GLib Dynamic Type System</title>
-
- <para>
- A type, as manipulated by the GLib type system, is much more generic than what
- is usually understood as an Object type. It is best explained by looking at the
- structure and the functions used to register new types in the type system.
- <programlisting>
-typedef struct _GTypeInfo GTypeInfo;
-struct _GTypeInfo
-{
- /* interface types, classed types, instantiated types */
- guint16 class_size;
-
- GBaseInitFunc base_init;
- GBaseFinalizeFunc base_finalize;
-
- /* classed types, instantiated types */
- GClassInitFunc class_init;
- GClassFinalizeFunc class_finalize;
- gconstpointer class_data;
-
- /* instantiated types */
- guint16 instance_size;
- guint16 n_preallocs;
- GInstanceInitFunc instance_init;
-
- /* value handling */
- const GTypeValueTable *value_table;
-};
-GType g_type_register_static (GType parent_type,
- const gchar *type_name,
- const GTypeInfo *info,
- GTypeFlags flags);
-GType g_type_register_fundamental (GType type_id,
- const gchar *type_name,
- const GTypeInfo *info,
- const GTypeFundamentalInfo *finfo,
- GTypeFlags flags);
- </programlisting>
- </para>
-
- <para>
- <function><link linkend="g-type-register-static">g_type_register_static</link></function> and
- <function><link linkend="g-type-register-fundamental">g_type_register_fundamental</link></function>
- are the C functions, defined in
- <filename>gtype.h</filename> and implemented in <filename>gtype.c</filename>
- which you should use to register a new <link linkend="GType"><type>GType</type></link> in the program's type system.
- It is not likely you will ever need to use
- <function><link linkend="g-type-register-fundamental">g_type_register_fundamental</link></function> (you have to be Tim Janik
- to do that) but in case you want to, the last chapter explains how to create
- 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>
- Fundamental types are top-level types which do not derive from any other type
- while other non-fundamental types derive from other types.
- Upon initialization by <function><link linkend="g-type-init">g_type_init</link></function>, the type system not
- only initializes its internal data structures but it also registers a number of core
- types: some of these are fundamental types. Others are types derived from these
- fundamental types.
- </para>
-
- <para>
- Fundamental and non-fundamental types are defined by:
- <itemizedlist>
- <listitem><para>
- class size: the class_size field in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>.
- </para></listitem>
- <listitem><para>
- class initialization functions (C++ constructor): the base_init and
- class_init fields in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>.
- </para></listitem>
- <listitem><para>
- class destruction functions (C++ destructor): the base_finalize and
- class_finalize fields in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>.
- </para></listitem>
- <listitem><para>
- instance size (C++ parameter to new): the instance_size field in
- <link linkend="GTypeInfo"><type>GTypeInfo</type></link>.
- </para></listitem>
- <listitem><para>
- instantiation policy (C++ type of new operator): the n_preallocs
- field in <link linkend="GTypeInfo"><type>GTypeInfo</type></link>.
- </para></listitem>
- <listitem><para>
- copy functions (C++ copy operators): the value_table field in
- <link linkend="GTypeInfo"><type>GTypeInfo</type></link>.
- </para></listitem>
- <listitem><para>
- type characteristic flags: <link linkend="GTypeFlags"><type>GTypeFlags</type></link>.
- </para></listitem>
- </itemizedlist>
- Fundamental types are also defined by a set of <link linkend="GTypeFundamentalFlags"><type>GTypeFundamentalFlags</type></link>
- which are stored in a <link linkend="GTypeFundamentalInfo"><type>GTypeFundamentalInfo</type></link>.
- Non-fundamental types are furthermore defined by the type of their parent which is
- passed as the parent_type parameter to <function><link linkend="g-type-register-static">g_type_register_static</link></function>
- and <function><link linkend="g-type-register-dynamic">g_type_register_dynamic</link></function>.
- </para>
-
- <sect1 id="gtype-copy">
- <title>Copy functions</title>
-
- <para>
- The major common point between <emphasis>all</emphasis> GLib types (fundamental and
- non-fundamental, classed and non-classed, instantiable and non-instantiable) is that
- they can all be manipulated through a single API to copy/assign them.
- </para>
-
- <para>
- The <link linkend="GValue"><type>GValue</type></link> structure is used as an abstract container for all of these
- types. Its simplistic API (defined in <filename>gobject/gvalue.h</filename>) can be
- used to invoke the value_table functions registered
- during type registration: for example <function><link linkend="g-value-copy">g_value_copy</link></function> copies the
- content of a <link linkend="GValue"><type>GValue</type></link> to another <link linkend="GValue"><type>GValue</type></link>. This is similar
- to a C++ assignment which invokes the C++ copy operator to modify the default
- bit-by-bit copy semantics of C++/C structures/classes.
- </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>
- instance pointer (sample code for this is located in the source tarball for this document in
- <filename>sample/gtype/test.c</filename>):
-<programlisting>
-static void test_int (void)
-{
- GValue a_value = G_VALUE_INIT;
- GValue b_value = G_VALUE_INIT;
- guint64 a, b;
-
- a = 0xdeadbeaf;
-
- g_value_init (&a_value, G_TYPE_UINT64);
- g_value_set_uint64 (&a_value, a);
-
- g_value_init (&b_value, G_TYPE_UINT64);
- g_value_copy (&a_value, &b_value);
-
- b = g_value_get_uint64 (&b_value);
-
- if (a == b) {
- g_print ("Yay !! 10 lines of code to copy around a uint64.\n");
- } else {
- g_print ("Are you sure this is not a Z80 ?\n");
- }
-}
-
-static void test_object (void)
-{
- GObject *obj;
- GValue obj_vala = G_VALUE_INIT;
- GValue obj_valb = G_VALUE_INIT;
- obj = g_object_new (MAMAN_TYPE_BAR, NULL);
-
- g_value_init (&obj_vala, MAMAN_TYPE_BAR);
- g_value_set_object (&obj_vala, obj);
-
- 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.
- */
- g_value_copy (&obj_vala, &obj_valb);
-
- g_object_unref (G_OBJECT (obj));
- g_object_unref (G_OBJECT (obj));
-}
-</programlisting>
- The important point about the above code is that the exact semantics of the copy calls
- is undefined since they depend on the implementation of the copy function. Certain
- copy functions might decide to allocate a new chunk of memory and then to copy the
- data from the source to the destination. Others might want to simply increment
- the reference count of the instance and copy the reference to the new GValue.
- </para>
-
- <para>
- The value_table used to specify these assignment functions is defined in
- <filename>gtype.h</filename> and is thoroughly described in the
- API documentation provided with GObject (for once ;-) which is why we will
- not detail its exact semantics.
- <programlisting>
-typedef struct _GTypeValueTable GTypeValueTable;
-struct _GTypeValueTable
-{
- void (*value_init) (GValue *value);
- void (*value_free) (GValue *value);
- void (*value_copy) (const GValue *src_value,
- GValue *dest_value);
- /* varargs functionality (optional) */
- gpointer (*value_peek_pointer) (const GValue *value);
- gchar *collect_format;
- gchar* (*collect_value) (GValue *value,
- guint n_collect_values,
- GTypeCValue *collect_values,
- guint collect_flags);
- gchar *lcopy_format;
- gchar* (*lcopy_value) (const GValue *value,
- guint n_collect_values,
- GTypeCValue *collect_values,
- guint collect_flags);
-};
- </programlisting>
- 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.
- </para>
- </sect1>
-
- <sect1 id="gtype-conventions">
- <title>Conventions</title>
-
-
- <para>
- There are a number of conventions users are expected to follow when creating new types
- which are to be exported in a header file:
- <itemizedlist>
- <listitem><para>
- Use the <function>object_method</function> pattern for function names: to invoke
- the method named foo on an instance of object type bar, call
- <function>bar_foo</function>.
- </para></listitem>
- <listitem><para>Use prefixing to avoid namespace conflicts with other projects.
- If your library (or application) is named <emphasis>Maman</emphasis>,
- <footnote>
- <para>
- <emphasis>Maman</emphasis> is the French word for <emphasis>mum</emphasis>
- or <emphasis>mother</emphasis> - nothing more and nothing less.
- </para>
- </footnote>
-
- prefix all your function names with <emphasis>maman_</emphasis>.
- For example: <function>maman_object_method</function>.
- </para></listitem>
- <listitem><para>Create a macro named <function>PREFIX_TYPE_OBJECT</function> which always
- returns the GType for the associated object type. For an object of type
- <emphasis>Bar</emphasis> in a library prefixed by <emphasis>maman</emphasis>,
- use: <function>MAMAN_TYPE_BAR</function>.
- It is common although not a convention to implement this macro using either a global
- static variable or a function named <function>prefix_object_get_type</function>.
- We will follow the function pattern wherever possible in this document.
- </para></listitem>
- <listitem><para>Create a macro named <function>PREFIX_OBJECT (obj)</function> which
- returns a pointer of type <type>PrefixObject</type>. This macro is used to enforce
- static type safety by doing explicit casts wherever needed. It also enforces
- dynamic type safety by doing runtime checks. It is possible to disable the dynamic
- type checks in production builds (see <link linkend="glib-building">building glib</link>).
- For example, we would create
- <function>MAMAN_BAR (obj)</function> to keep the previous example.
- </para></listitem>
- <listitem><para>If the type is classed, create a macro named
- <function>PREFIX_OBJECT_CLASS (klass)</function>. This macro
- is strictly equivalent to the previous casting macro: it does static casting with
- dynamic type checking of class structures. It is expected to return a pointer
- to a class structure of type <type>PrefixObjectClass</type>. Again, an example is:
- <function>MAMAN_BAR_CLASS</function>.
- </para></listitem>
- <listitem><para>Create a macro named <function>PREFIX_IS_BAR (obj)</function>: this macro is expected
- to return a <type>gboolean</type> which indicates whether or not the input
- object instance pointer of type BAR.
- </para></listitem>
- <listitem><para>If the type is classed, create a macro named
- <function>PREFIX_IS_OBJECT_CLASS (klass)</function> which, as above, returns a boolean
- if the input class pointer is a pointer to a class of type OBJECT.
- </para></listitem>
- <listitem><para>If the type is classed, create a macro named
- <function>PREFIX_OBJECT_GET_CLASS (obj)</function>
- which returns the class pointer associated to an instance of a given type. This macro
- is used for static and dynamic type safety purposes (just like the previous casting
- macros).
- </para></listitem>
- </itemizedlist>
- The implementation of these macros is pretty straightforward: a number of simple-to-use
- macros are provided in <filename>gtype.h</filename>. For the example we used above, we would
- write the following trivial code to declare the macros:
-<programlisting>
-#define MAMAN_TYPE_BAR (maman_bar_get_type ())
-#define MAMAN_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_TYPE_BAR, MamanBar))
-#define MAMAN_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MAMAN_TYPE_BAR, MamanBarClass))
-#define MAMAN_IS_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_TYPE_BAR))
-#define MAMAN_IS_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MAMAN_TYPE_BAR))
-#define MAMAN_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MAMAN_TYPE_BAR, MamanBarClass))
-</programlisting>
- <note><simpara>Stick to the naming <varname>klass</varname> as <varname>class</varname> is a registered c++ keyword.</simpara></note>
- </para>
-
- <para>
- The following code shows how to implement the <function>maman_bar_get_type</function>
- function:
-<programlisting>
-GType maman_bar_get_type (void)
-{
- static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
- /* You fill this structure. */
- };
- type = g_type_register_static (G_TYPE_OBJECT,
- "MamanBarType",
- &info, 0);
- }
- return type;
-}
-</programlisting>
- </para>
-
- <para>
- When having no special requirements you also can use the <function>G_DEFINE_TYPE</function>
- macro:
-<programlisting>
-G_DEFINE_TYPE (MamanBar, maman_bar, G_TYPE_OBJECT)
-</programlisting>
- </para>
-
- </sect1>
-
- <sect1 id="gtype-non-instantiable">
- <title>Non-instantiable non-classed fundamental types</title>
-
- <para>
- A lot of types are not instantiable by the type system and do not have
- a class. Most of these types are fundamental trivial types such as <emphasis>gchar</emphasis>,
- registered in <function>_g_value_types_init</function> (in <filename>gvaluetypes.c</filename>).
- </para>
-
- <para>
- To register such a type in the type system, you just need to fill the
- <link linkend="GTypeInfo"><type>GTypeInfo</type></link> structure with zeros since these types are also most of the time
- fundamental:
- <programlisting>
- GTypeInfo info = {
- 0, /* class_size */
- NULL, /* base_init */
- NULL, /* base_destroy */
- NULL, /* class_init */
- NULL, /* class_destroy */
- NULL, /* class_data */
- 0, /* instance_size */
- 0, /* n_preallocs */
- NULL, /* instance_init */
- NULL, /* value_table */
- };
- static const GTypeValueTable value_table = {
- value_init_long0, /* value_init */
- NULL, /* value_free */
- value_copy_long0, /* value_copy */
- NULL, /* value_peek_pointer */
- "i", /* collect_format */
- value_collect_int, /* collect_value */
- "p", /* lcopy_format */
- value_lcopy_char, /* lcopy_value */
- };
- info.value_table = &value_table;
- type = g_type_register_fundamental (G_TYPE_CHAR, "gchar", &info, &finfo, 0);
- </programlisting>
- </para>
-
-
- <para>
- Having non-instantiable types might seem a bit useless: what good is a type
- if you cannot instantiate an instance of that type ? Most of these types
- are used in conjunction with <link linkend="GValue"><type>GValue</type></link>s: a GValue is initialized
- with an integer or a string and it is passed around by using the registered
- type's value_table. <link linkend="GValue"><type>GValue</type></link>s (and by extension these trivial fundamental
- types) are most useful when used in conjunction with object properties and signals.
- </para>
-
- </sect1>
-
- <sect1 id="gtype-instantiable-classed">
- <title>Instantiable classed types: objects</title>
-
- <para>
- Types which are registered with a class and are declared instantiable are
- what most closely resembles an <emphasis>object</emphasis>.
- Although <link linkend="GObject"><type>GObject</type></link>s (detailed in <xref linkend="chapter-gobject"/>)
- are the most well known type of instantiable
- classed types, other kinds of similar objects used as the base of an inheritance
- hierarchy have been externally developed and they are all built on the fundamental
- features described below.
- </para>
-
- <para>
- For example, the code below shows how you could register
- such a fundamental object type in the type system:
-<programlisting>
-typedef struct {
- GObject parent;
- /* instance members */
- int field_a;
-} MamanBar;
-
-typedef struct {
- GObjectClass parent;
- /* class members */
- void (*do_action_public_virtual) (MamanBar *self, guint8 i);
-
- void (*do_action_public_pure_virtual) (MamanBar *self, guint8 i);
-} MamanBarClass;
-
-#define MAMAN_TYPE_BAR (maman_bar_get_type ())
-
-GType
-maman_bar_get_type (void)
-{
- static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof (MamanBarClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) foo_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (MamanBar),
- 0, /* n_preallocs */
- (GInstanceInitFunc) NULL /* instance_init */
- };
- type = g_type_register_static (G_TYPE_OBJECT,
- "BarType",
- &info, 0);
- }
- return type;
-}
-</programlisting>
- Upon the first call to <function>maman_bar_get_type</function>, the type named
- <emphasis>BarType</emphasis> will be registered in the type system as inheriting
- from the type <emphasis>G_TYPE_OBJECT</emphasis>.
- </para>
-
- <para>
- Every object must define two structures: its class structure and its
- instance structure. All class structures must contain as first member
- a <link linkend="GTypeClass"><type>GTypeClass</type></link> structure. All instance structures must contain as first
- member a <link linkend="GTypeInstance"><type>GTypeInstance</type></link> structure. The declaration of these C types,
- coming from <filename>gtype.h</filename> is shown below:
-<programlisting>
-struct _GTypeClass
-{
- GType g_type;
-};
-struct _GTypeInstance
-{
- GTypeClass *g_class;
-};
-</programlisting>
- These constraints allow the type system to make sure that every object instance
- (identified by a pointer to the object's instance structure) contains in its
- first bytes a pointer to the object's class structure.
- </para>
- <para>
- This relationship is best explained by an example: let's take object B which
- inherits from object A:
-<programlisting>
-/* A definitions */
-typedef struct {
- GTypeInstance parent;
- int field_a;
- int field_b;
-} A;
-typedef struct {
- GTypeClass parent_class;
- void (*method_a) (void);
- void (*method_b) (void);
-} AClass;
-
-/* B definitions. */
-typedef struct {
- A parent;
- int field_c;
- int field_d;
-} B;
-typedef struct {
- AClass parent_class;
- void (*method_c) (void);
- void (*method_d) (void);
-} BClass;
-</programlisting>
- 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
- to B's class structure.
- </para>
-
- <para>
- Thanks to these simple conditions, it is possible to detect the type of every
- object instance by doing:
-<programlisting>
-B *b;
-b->parent.parent.g_class->g_type
-</programlisting>
- or, more quickly:
-<programlisting>
-B *b;
-((GTypeInstance*)b)->g_class->g_type
-</programlisting>
- </para>
-
- <sect2 id="gtype-instantiable-classed-init-done">
- <title>Initialization and Destruction</title>
-
- <para>
- instantiation of these types can be done with
- <function><link linkend="g-type-create-instance">g_type_create_instance</link></function>:
-<programlisting>
-GTypeInstance* g_type_create_instance (GType type);
-void g_type_free_instance (GTypeInstance *instance);
-</programlisting>
- <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)
- declared by the user are used to get a buffer to hold the object's instance
- structure.
- </para>
-
- <para>
- If this is the first instance of the object ever created, the type system must create a class structure.
- It allocates a buffer to hold the object's class structure and initializes it. The first part of the
- class structure (ie: the embedded parent class structure) is initialized by copying the contents from
- the class structure of the parent class. The rest of class structure is initialized to zero. If there
- is no parent, the entire class structure is initialized to zero. The type system then invokes the
- base_class_initialization functions (<link linkend="GBaseInitFunc"><type>GBaseInitFunc</type></link>) from topmost
- fundamental object to bottom-most most derived object. The object's class_init
- (<link linkend="GClassInitFunc"><type>GClassInitFunc</type></link>) function is invoked afterwards to complete
- initialization of the class structure.
- Finally, the object's interfaces are initialized (we will discuss interface initialization
- in more detail later).
- </para>
-
- <para>
- Once the type system has a pointer to an initialized class structure, it sets the object's
- instance class pointer to the object's class structure and invokes the object's
- instance_init (<link linkend="GInstanceInitFunc"><type>GInstanceInitFunc</type></link>)functions, from top-most fundamental
- type to bottom-most most derived type.
- </para>
-
- <para>
- Object instance destruction through <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> is very simple:
- the instance structure is returned to the instance pool if there is one and if this was the
- last living instance of the object, the class is destroyed.
- </para>
-
-
- <para>
- Class destruction (the concept of destruction is sometimes partly
- referred to as finalization in GType) is the symmetric process of
- the initialization: interfaces are destroyed first.
- Then, the most derived
- class_finalize (<link linkend="GClassFinalizeFunc"><type>GClassFinalizeFunc</type></link>) function is invoked. The
- base_class_finalize (<link linkend="GBaseFinalizeFunc"><type>GBaseFinalizeFunc</type></link>) functions are
- Finally invoked from bottom-most most-derived type to top-most fundamental type and
- the class structure is freed.
- </para>
-
- <para>
- As many readers have now understood it, the base initialization/finalization process is
- very similar to the C++ constructor/destructor paradigm. The practical details are different
- though and it is important not to get confused by superficial similarities.
- GTypes have no instance destruction mechanism. It is
- the user's responsibility to implement correct destruction semantics on top
- of the existing GType code. (this is what GObject does. See
- <xref linkend="chapter-gobject"/>)
- Furthermore, C++ code equivalent to the base_init
- and class_init callbacks of GType is usually not needed because C++ cannot really create object
- types at runtime.
- </para>
-
- <para>
- The instantiation/finalization process can be summarized as follows:
- <table id="gtype-init-fini-table">
- <title>GType Instantiation/Finalization</title>
- <tgroup cols="3">
- <colspec colwidth="*" colnum="1" align="left"/>
- <colspec colwidth="*" colnum="2" align="left"/>
- <colspec colwidth="8*" colnum="3" align="left"/>
-
- <thead>
- <row>
- <entry>Invocation time</entry>
- <entry>Function Invoked</entry>
- <entry>Function's parameters</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry morerows="2">First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry>
- <entry>type's base_init function</entry>
- <entry>On the inheritance tree of classes from fundamental type to target type.
- base_init is invoked once for each class structure.</entry>
- </row>
- <row>
- <!--entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry-->
- <entry>target type's class_init function</entry>
- <entry>On target type's class structure</entry>
- </row>
- <row>
- <!--entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry-->
- <entry>interface initialization, see
- <xref linkend="gtype-non-instantiable-classed-init"/></entry>
- <entry></entry>
- </row>
- <row>
- <entry>Each call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for target type</entry>
- <entry>target type's instance_init function</entry>
- <entry>On object's instance</entry>
- </row>
- <row>
- <entry morerows="2">Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for target type</entry>
- <entry>interface destruction, see
- <xref linkend="gtype-non-instantiable-classed-dest"/></entry>
- <entry></entry>
- </row>
- <row>
- <!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for target type</entry-->
- <entry>target type's class_finalize function</entry>
- <entry>On target type's class structure</entry>
- </row>
- <row>
- <!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for target type</entry-->
- <entry>type's base_finalize function</entry>
- <entry>On the inheritance tree of classes from fundamental type to target type.
- base_finalize is invoked once for each class structure.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </para>
-
- </sect2>
-
- </sect1>
-
- <sect1 id="gtype-non-instantiable-classed">
- <title>Non-instantiable classed types: interfaces</title>
-
- <para>
- GType's interfaces are very similar to Java's interfaces. They allow
- to describe a common API that several classes will adhere to.
- Imagine the play, pause and stop buttons on hi-fi equipment - those can
- 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
- classed type which derives from
- <link linkend="GTypeInterface"><type>GTypeInterface</type></link>. The following piece of code declares such an interface.
-<programlisting>
-#define MAMAN_TYPE_IBAZ (maman_ibaz_get_type ())
-#define MAMAN_IBAZ(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAMAN_TYPE_IBAZ, MamanIbaz))
-#define MAMAN_IS_IBAZ(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAMAN_TYPE_IBAZ))
-#define MAMAN_IBAZ_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), MAMAN_TYPE_IBAZ, MamanIbazInterface))
-
-typedef struct _MamanIbaz MamanIbaz; /* dummy object */
-typedef struct _MamanIbazInterface MamanIbazInterface;
-
-struct _MamanIbazInterface {
- GTypeInterface parent;
-
- void (*do_action) (MamanIbaz *self);
-};
-
-GType maman_ibaz_get_type (void);
-
-void maman_ibaz_do_action (MamanIbaz *self);
-</programlisting>
- The interface function, <function>maman_ibaz_do_action</function> is implemented
- in a pretty simple way:
-<programlisting>
-void maman_ibaz_do_action (MamanIbaz *self)
-{
- MAMAN_IBAZ_GET_INTERFACE (self)->do_action (self);
-}
-</programlisting>
- <function>maman_ibaz_get_type</function> registers a type named <emphasis>MamanIBaz</emphasis>
- which inherits from G_TYPE_INTERFACE. All interfaces must be children of G_TYPE_INTERFACE in the
- inheritance tree.
- </para>
-
- <para>
- An interface is defined by only one structure which must contain as first member
- a <link linkend="GTypeInterface"><type>GTypeInterface</type></link> structure. The interface structure is expected to
- contain the function pointers of the interface methods. It is good style to
- define helper functions for each of the interface methods which simply call
- the interface' method directly: <function>maman_ibaz_do_action</function>
- is one of these.
- </para>
-
- <para>
- Once an interface type is registered, you must register implementations for these
- interfaces. The function named <function>maman_baz_get_type</function> registers
- a new GType named MamanBaz which inherits from <link linkend="GObject"><type>GObject</type></link> and which
- implements the interface <type>MamanIBaz</type>.
-<programlisting>
-static void maman_baz_do_action (MamanIbaz *self)
-{
- g_print ("Baz implementation of IBaz interface Action.\n");
-}
-
-
-static void
-baz_interface_init (gpointer g_iface,
- gpointer iface_data)
-{
- MamanIbazInterface *iface = (MamanIbazInterface *)g_iface;
- iface->do_action = maman_baz_do_action;
-}
-
-GType
-maman_baz_get_type (void)
-{
- static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof (MamanBazInterface),
- NULL, /* base_init */
- NULL, /* base_finalize */
- NULL, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (MamanBaz),
- 0, /* n_preallocs */
- NULL /* instance_init */
- };
- static const GInterfaceInfo ibaz_info = {
- (GInterfaceInitFunc) baz_interface_init, /* interface_init */
- NULL, /* interface_finalize */
- NULL /* interface_data */
- };
- type = g_type_register_static (G_TYPE_OBJECT,
- "MamanBazType",
- &info, 0);
- g_type_add_interface_static (type,
- MAMAN_TYPE_IBAZ,
- &ibaz_info);
- }
- return type;
-}
-</programlisting>
- </para>
-
- <para>
- <function><link linkend="g-type-add-interface-static">g_type_add_interface_static</link></function> records in the type system that
- a given type implements also <type>FooInterface</type>
- (<function>foo_interface_get_type</function> returns the type of
- <type>FooInterface</type>).
- The <link linkend="GInterfaceInfo"><type>GInterfaceInfo</type></link> structure holds
- information about the implementation of the interface:
-<programlisting>
-struct _GInterfaceInfo
-{
- GInterfaceInitFunc interface_init;
- GInterfaceFinalizeFunc interface_finalize;
- gpointer interface_data;
-};
-</programlisting>
- </para>
- <para>
- When having no special requirements you also can use the <function>G_DEFINE_INTERFACE</function> macro:
-<programlisting>
-G_DEFINE_INTERFACE (MamanBaz, maman_baz, G_TYPE_OBJECT)
-</programlisting>
- </para>
-
-
- <sect2 id="gtype-non-instantiable-classed-init">
- <title>Interface Initialization</title>
-
- <para>
- When an instantiable classed type which registered an interface
- implementation is created for the first time, its class structure
- is initialized following the process
- described in <xref linkend="gtype-instantiable-classed"/>.
- After that, the interface implementations associated with
- the type are initialized.
- </para>
-
- <para>
- 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.
- </para>
-
- <para>
- Finally, the interface' most-derived <function>base_init</function> function and then
- the implementation's <function>interface_init</function>
- function are invoked. It is important to understand that if there are multiple
- implementations of an interface the <function>base_init</function> and
- <function>interface_init</function> functions will be
- invoked once for each implementation initialized.
- </para>
-
- <para>
- It is thus common for base_init functions to hold a local static boolean variable
- which makes sure that the interface type is initialized only once even if there are
- multiple implementations of the interface:
-<programlisting>
-static void
-maman_ibaz_base_init (gpointer g_iface)
-{
- static gboolean initialized = FALSE;
-
- if (!initialized) {
- /* create interface signals here. */
- initialized = TRUE;
- }
-}
-</programlisting>
- </para>
-
- <para>
- If you have found the stuff about interface hairy, you are right: it is hairy but
- there is not much I can do about it. What I can do is summarize what you need to know
- about interfaces:
- </para>
-
- <para>
- The above process can be summarized as follows:
- <table id="ginterface-init-table">
- <title>Interface Initialization</title>
- <tgroup cols="3">
- <colspec colwidth="*" colnum="1" align="left"/>
- <colspec colwidth="*" colnum="2" align="left"/>
- <colspec colwidth="8*" colnum="3" align="left"/>
-
- <thead>
- <row>
- <entry>Invocation time</entry>
- <entry>Function Invoked</entry>
- <entry>Function's parameters</entry>
- <entry>Remark</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry morerows="1">First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for type
- implementing interface
- </entry>
- <entry>interface' base_init function</entry>
- <entry>On interface' vtable</entry>
- <entry>Register interface' signals here (use a local static
- boolean variable as described above to make sure not to register them
- twice.).</entry>
- </row>
- <row>
- <!--entry>First call to <function><link linkend="g-type-create-instance">g_type_create_instance</link></function> for type
- implementing interface
- </entry-->
- <entry>interface' interface_init function</entry>
- <entry>On interface' vtable</entry>
- <entry>
- Initialize interface' implementation. That is, initialize the interface
- method pointers in the interface structure to the function's implementation.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- It is highly unlikely (i.e. I do not know of <emphasis>anyone</emphasis> who actually
- used it) you will ever need other more fancy things such as the ones described in the
- following section (<xref linkend="gtype-non-instantiable-classed-dest"/>).
- </para>
-
- </sect2>
-
- <sect2 id="gtype-non-instantiable-classed-dest">
- <title>Interface Destruction</title>
-
- <para>
- When the last instance of an instantiable type which registered
- an interface implementation is destroyed, the interface's
- implementations associated to the type are destroyed.
- </para>
-
- <para>
- To destroy an interface implementation, GType first calls the
- implementation's <function>interface_finalize</function> function
- and then the interface's most-derived
- <function>base_finalize</function> function.
- </para>
-
- <para>
- Again, it is important to understand, as in
- <xref linkend="gtype-non-instantiable-classed-init"/>,
- that both <function>interface_finalize</function> and <function>base_finalize</function>
- are invoked exactly once for the destruction of each implementation of an interface. Thus,
- if you were to use one of these functions, you would need to use a static integer variable
- which would hold the number of instances of implementations of an interface such that
- the interface's class is destroyed only once (when the integer variable reaches zero).
- </para>
-
- <para>
- The above process can be summarized as follows:
- <table id="ginterface-fini-table">
- <title>Interface Finalization</title>
- <tgroup cols="3">
- <colspec colwidth="*" colnum="1" align="left"/>
- <colspec colwidth="*" colnum="2" align="left"/>
- <colspec colwidth="8*" colnum="3" align="left"/>
-
- <thead>
- <row>
- <entry>Invocation time</entry>
- <entry>Function Invoked</entry>
- <entry>Function's parameters</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry morerows="1">Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function> for type
- implementing interface
- </entry>
- <entry>interface' interface_finalize function</entry>
- <entry>On interface' vtable</entry>
- </row>
- <row>
- <!--entry>Last call to <function><link linkend="g-type-free-instance">g_type_free_instance</link></function>for type
- implementing interface
- </entry-->
- <entry>interface' base_finalize function</entry>
- <entry>On interface' vtable</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </para>
- </sect2>
- </sect1>
- </chapter>