GObject

Class and instance

GObject instance is created with g_object_new function. GObject has not only instances but also classes.

In a broad sense, GObject means the object which includes its class and instances. In a narrow sense, GObject is a definition of a C structure.

typedef struct _GObject  GObject;
struct  _GObject
{
  GTypeInstance  g_type_instance;
  
  /*< private >*/
  guint          ref_count;  /* (atomic) */
  GData         *qdata;
};

The g_object_new function allocates GObject-sized memory, initializes the memory and returns the pointer to the memory. The memory is a GObject instance.

In the same way, the class of GObject is memory allocated by g_object_new and its structure is defined with GObjectClass. The following is extracted from gobject.h. But you don’t need to know the details of the structure now.

struct  _GObjectClass
{
  GTypeClass   g_type_class;

  /*< private >*/
  GSList      *construct_properties;

  /*< public >*/
  /* seldom overridden */
  GObject*   (*constructor)     (GType                  type,
                                 guint                  n_construct_properties,
                                 GObjectConstructParam *construct_properties);
  /* overridable methods */
  void       (*set_property)        (GObject        *object,
                                         guint           property_id,
                                         const GValue   *value,
                                         GParamSpec     *pspec);
  void       (*get_property)        (GObject        *object,
                                         guint           property_id,
                                         GValue         *value,
                                         GParamSpec     *pspec);
  void       (*dispose)         (GObject        *object);
  void       (*finalize)        (GObject        *object);
  /* seldom overridden */
  void       (*dispatch_properties_changed) (GObject      *object,
                         guint     n_pspecs,
                         GParamSpec  **pspecs);
  /* signals */
  void       (*notify)          (GObject    *object,
                     GParamSpec *pspec);

  /* called when done constructing */
  void       (*constructed)     (GObject    *object);

  /*< private >*/
  gsize     flags;

  gsize         n_construct_properties;

  gpointer pspecs;
  gsize n_pspecs;

  /* padding */
  gpointer  pdummy[3];
};

The programs for GObject are included in GLib source files. You can download the GLib source files from GNOME download page.

There are sample programs in src/misc directory in the GObject tutorial repository. You can compile them by:

$ cd src/misc
$ meson setup _build
$ ninja -C _build

One of the programs is example1.c. Its code is as follows.

#include <glib-object.h>

int
main (int argc, char **argv) {
  GObject *instance1, *instance2;
  GObjectClass *class1, *class2;
  
  instance1 = g_object_new (G_TYPE_OBJECT, NULL);
  instance2 = g_object_new (G_TYPE_OBJECT, NULL);
  g_print ("The address of instance1 is %p\n", instance1);
  g_print ("The address of instance2 is %p\n", instance2);

  class1 = G_OBJECT_GET_CLASS (instance1);
  class2 = G_OBJECT_GET_CLASS (instance2);
  g_print ("The address of the class of instance1 is %p\n", class1);
  g_print ("The address of the class of instance2 is %p\n", class2);

  g_object_unref (instance1);
  g_object_unref (instance2);

  return 0;
}

Now, execute it.

$ cd src/misc; _build/example1
The address of instance1 is 0x55895eaf7ad0
The address of instance2 is 0x55895eaf7af0
The address of the class of instance1 is 0x55895eaf7880
The address of the class of instance2 is 0x55895eaf7880

The locations of two instances instance1 and instance2 are different. Each instance has its own memory. The locations of two classes class1 and class2 are the same. Two GObject instances share the same class.

Class and Instance

Reference count

GObject instance has its own memory. They are allocated by the system when it is created. If it becomes useless, the memory must be freed. However, how can we determine whether it is useless? GObject system provides reference count to solve the problem.

An instance is created and used by other instance or the main program. That is to say, the instance is referred. If the instance is referred by A and B, then the number of the reference is two. This number is called reference count. Let’s think about a scenario like this:

A program example2.c is based on the scenario above.

#include <glib-object.h>

static void
show_ref_count (GObject *instance) {
  if (G_IS_OBJECT (instance))
    /* Users should not use ref_count member in their program. */
    /* This is only for demonstration. */
    g_print ("Reference count is %d.\n", instance->ref_count);
  else
    g_print ("Instance is not GObject.\n");
}

int
main (int argc, char **argv) {
  GObject *instance;
  
  instance = g_object_new (G_TYPE_OBJECT, NULL);
  g_print ("Call g_object_new.\n");
  show_ref_count (instance);
  g_object_ref (instance);
  g_print ("Call g_object_ref.\n");
  show_ref_count (instance);
  g_object_unref (instance);
  g_print ("Call g_object_unref.\n");
  show_ref_count (instance);
  g_object_unref (instance);
  g_print ("Call g_object_unref.\n");
  g_print ("Now the reference count is zero and the instance is destroyed.\n");
  g_print ("The instance memories are possibly returned to the system.\n");
  g_print ("Therefore, the access to the same address may cause a segmentation error.\n");
  
  return 0;
}

Now execute it.

$ cd src/misc; _build/example2
bash: cd: src/misc: No such file or directory
Call g_object_new.
Reference count is 1.
Call g_object_ref.
Reference count is 2.
Call g_object_unref.
Reference count is 1.
Call g_object_unref.
Now the reference count is zero and the instance is destroyed.
The instance memories are possibly returned to the system.
Therefore, the access to the same address may cause a segmentation error.

example2 shows:

Initialization and destruction process

The actual process of GObject initialization and destruction is very complex. The following is simplified description without details.

Initialization

  1. Registers GObject type with the type system. This is done in the GLib initialization process before the function main is called. (If the compiler is gcc, then __attribute__ ((constructor)) is used to qualify the initialization function. Refer to GCC manual.)
  2. Allocates memory for GObjectClass and GObject structure.
  3. Initializes the GObjectClass structure memory. This memory will be the class of GObject.
  4. Initializes the GObject structure memory. This memory will be the instance of GObject.

This initialization process is carried out when g_object_new function is called for the first time. At the second and subsequent call for g_object_new, it performs only two processes: (1) memory allocation for GObject structure (2) initialization for the memory. g_object_new returns the pointer that points the instance (the memory allocated for the GObject structure).

Destruction

  1. Destroys GObject instance. The memory for the instance is freed.

GObject type is a static type. Static type never destroys its class. So, even if the destroyed instance is the last instance, the class still remains.

When you write code to define a child object of GObject, It is important to understand the process above. The detailed process will be explained in the later sections.