Location>code7788 >text

GObject Study Notes (I) Classes and Instances

Popularity:544 ℃/2024-11-17 14:05:44

preamble

Recent ReadsAravissource code, which makes heavy use of GObject, and was going to learn it.

This series of notes only mainly for beginners, will not be very in-depth exploration of the details of the source code, focusing on the introduction of the basic use of GObject.

This series of notes referencesGObject Tutorial for beginners

This article is available atpersonal blogReading in the center, the experience is more

Set a shield: the terms defined in the text are only for a better understanding of the GObject and are not authoritative.

Classes and instances

In GObject, each instantiable class type is associated with two structures: a class structure and an instance structure.

  • The class constructor will be registered with the type system (the exact registration is described in thenext sectionDiscussion), ing_object_newThe first time it is called, the type system checks to see if the corresponding class structure has been initialized to a class variable, and if not, it is created and initialized. All subsequent instance variables of that class will share this initialized class variable. Each class variable will only be created once.
  • Each time theg_object_newInstance variables are created whenever they are created.

In the GObject system, both class structures and instance structures are instantiated and occupy a specific space in memory. For ease of description, we will refer to instances assigned to class structures as "class variables" and instances assigned to instance structures as "instance variables".

The structure of a GObject instance is defined as follows

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

The structure of the GObject class is defined as follows (we can leave the details of the structure alone for now):

//file: 
typedef struct _GObjectClass             GObjectClass;
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 following is a simple example that demonstrates the use of GObject classes and instances.

//file:
#include <>

int main (int argc, char **argv)
{

    GObject* instance1,* instance2; //Pointer to an instance
    GObjectClass* class1,* class2; //Pointer to class
   
    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;
}

Among them:

  • g_object_newfunction creates the instance variable and returns a pointer to it. Before the instance variable is created for the first time, its corresponding class variable is also created and initialized.
  • parametersG_TYPE_OBJECTis the type identifier of the GObject base class, which is the core of the GObject type system and from which all other GObject types are derived.
  • macro (computing)G_OBJECT_GET_CLASSReturns a pointer to the class variable to which the argument belongs
  • g_object_unrefwill destroy the instance variable and free the memory.

Output:

The address of instance1 is 0x55d3ddc05600
The address of instance2 is 0x55d3ddc05620
The address of the class of instance1 is 0x55d3ddc05370
The address of the class of instance2 is 0x55d3ddc05370

It can be noticed that the addresses of the two instance variables are different, but the addresses of the class variables corresponding to the two instance variables are the same, because the two instance variables share a class variable

reference count

The concept of the reference counting mechanism is not introduced here

In GObject, GObject instances have a reference counting mechanism:

//file: 
#include <>
 
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;
}

Among them:

  • g_object_newCreate an instance variable and then set the reference count of the variable to 1
  • g_object_refAdd 1 to its reference count
  • g_object_unrefDecrement the reference count by 1. If the reference count is 0 at this point, destruct the variable.

Output:

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.

Initialization and destructuring processes

The actual process of GObject initialization and destruction is more complex. The following is a brief description without going into detail.

initialization

1. Register the GObject type with the type system. This is done during the initialization of GLib before calling the main function. (If the compiler is gcc, the__attribute__ ((constructor))used to qualify the initialization function.)
2. Allocate memory for GObjectClass and GObject structure
3. Initialize the GObjectClass structure memory. This memory will be the GObject class variables.
4. Initialize the GObject structure memory. This memory will be the instance variables of GObject.

The above initialization procedure is performed after the first call tog_object_newfunction is executed. On the second and subsequent calls to theg_object_newWhen it does so, it performs only two processes: ① allocate memory for the GObject structure ② initialize the memory.

disjointed

1. Destroy the GObject instance. Free the memory of the instance

GObject variable types are static types. A static type never destroys its class. Therefore, even if the instance variable that is destroyed is the last one, the class variable still exists until the program terminates.

reference article

1.GObject Tutorial for beginners

testimonials