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), in
g_object_new
The 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 the
g_object_new
Instance 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_new
function 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. - parameters
G_TYPE_OBJECT
is 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_CLASS
Returns a pointer to the class variable to which the argument belongs -
g_object_unref
will 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_new
Create an instance variable and then set the reference count of the variable to 1 -
g_object_ref
Add 1 to its reference count -
g_object_unref
Decrement 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_new
function is executed. On the second and subsequent calls to theg_object_new
When 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