Friday, September 7, 2018

Part 3. Deriving from GObject derived class - Object properties

In the previous post, we introduced a concept about getter and setter methods. Basically, they provide safer access to the class members. However, it is absolutely not necessary to have getters and/or setters for all class member. The decision to have or not to have getters and setters should be driven by the class design logic. Here, we will review two approaches to implement get/set methods. Let's start with an example where public API available to serve our getter and setter purpose. We continue our work on the MyPoint class expanding it. Let's add a public API to access our name member. As a reminder, our public structure should be:

1
2
3
4
5
6
typedef struct {
  gint x;
  gint y;
  gchar *name;
  /* stuff */
} MyPointPrivate;

Which corresponds to the derivable class from the part 2. For public API, we need to declare our methods in the header file and define them in the source file. The declaration in the header file is pretty straightforward and will be:

1
2
void my_point_set_name (MyPoint *self, const gchar *name);
const gchar *my_point_get_name (MyPoint *self);

The definition in the source file should be:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
void
my_point_set_name (MyPoint *self, 
                   const gchar *name)
{
  g_return_if_fail (self);
  
  MyPointPrivate *priv = my_point_get_instance_private (self);
  
  g_free (priv->name);
  priv->name = g_stdup (name);
}

const gchar*
my_point_get_name (MyPoint *self)
{
  g_return_val_if_fail (self, NULL);
  
  MyPointPrivate *priv = my_point_get_instance_private (self);
  
  return priv->name;
}

Did you notice some extra calls on line #5 and #16? They are common checkers for method parameters. Without those checkers, we may pass a NULL as the self argument and it will cause an error. Since we are trying to dereference it in the function. With these checkers, we know for sure that self is not NULL. GObject provides an alternative and a general approach to accomplish the same task. It is called GObject properties. How it works? We introduce a property for an object and associate that property to a class member. After that, when we manipulate the property we manipulate our class member. Let's implement a property for the class member name for our MyPoint class.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
enum {
  PROP_0,
  PROP_NAME,
  N_PROPERTIES
};

static GParamSpec *properties[N_PROPERTIES] = {NULL};

static void
my_point_set_property (GObject      *object,
                       guint         property_id,
                       const GValue *value,
                       GParamSpec   *pspec)
{
  MyPoint *self = MY_POINT(object);
  MyPointPrivate *priv = my_point_get_instance_private (self);

  switch (property_id)
    {
      case PROP_NAME:
        g_free (priv->name);
        priv->name = g_value_dup_string (value);
        break;
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
        break;
    }
}

static void
my_point_get_property (GObject      *object,
                       guint         property_id,
                       GValue       *value,
                       GParamSpec   *pspec)
{
  MyPoint *self = MY_POINT(object);
  MyPointPrivate *priv = my_point_get_instance_private (self);

  switch (property_id)
    {
      case PROP_NAME:
        g_value_set_string (value, priv->name);
        break;
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
        break;
    }
}


static void
my_point_class_init (MyPointClass *klass)
{
  GObjecClass *cobject = G_OBJECT(klass);

  cobject->get_property = my_point_get_property;
  cobject->set_property = my_point_set_property; 

  properties[PROP_NAME] = g_param_spec_string ("name",
                         "Name",
                         "Name of our point",
                         "Default value",
                         G_PARAM_READWRITE));  
  
  g_object_class_install_properties (cobject,N_PROPERTIES,properties);
}

Let's review this code line-by-line. In the beginning, we declare an enumerator that defines all properties. The property with value "0" is reserved for internal GObject use and should not be used in the user-written code. We can even remove it from our declaration and set the next member to have value "1":

1
2
3
4
enum {
  PROP_NAME = 1,
  N_PROPERTIES
};

On the line #7 (previous block) we declare an array to hold our properties and set all values to NULL. In the next two blocks, we define static functions to implement a code for our object to work with our properties. At the beginning of the function's body, we get an object to the private structure and then use the switch statement to work with each property based on passed property ID, which in fact enumerator values defined earlier. Pay attention to the object type we pass to our static methods. It is GValue. Because of that, it is very general and a user only needs to implement how to set/get values to the GValue variable. Exactly what we have in our switch statement. GObject class defines two pointers to functions that we need to set using our static functions: set_property and get_property (lines #56 and #57).  The next step would be setting values to our properties array. We should do this in our ..._class_init function. One-by-one, we need to set values for every element of our array. g_param_spec_... family of functions provides a convenient mechanism to create a GParamSpec instance. The user should use an appropriate function that corresponds to the type of member. In our case it is const gchar* , therefore, we use g_param_spec_string method. Please see a full list of the available methods in the official documentation. In the last step (line #65), we register our array with properties. That's it. Now, if we want to get a value of our name class member we need to use g_object_get() method and to set a new value for name, we should use g_object_set() method:

1
2
3
4
5
gchar *buffer;
MyPoint *point;

g_object_get (point,"name",&buffer,NULL);
g_object_set (point,"name",buffer,NULL);

The code should be self-explained. The first argument for both methods is our MyPoint instance. The second argument is our property name. To get a value we need to pass a reference to an object where we would like to have a copy. To set a new value we need to pass a regular object instance. We can repeat this step and get as many as we need properties at once. Just add more property-value pairs. In the end, we should terminate with NULL.
As you can see, two approaches are very similar for API user and can be used interchangeably as soon as an appropriate code to define properties was implemented. For library development, the generic approach is favorable since it provides a better binding implementation for other languages.

Part 2. Deriving from GObject based object

In the previous post, we discussed how to derive a final class from the GObject class. Here, I would like to focus on a derived object that can be used for the following subclassing. This is a common situation for library development, where classes, usually, are expected to be further subclassed. We will continue our journey using the same files from the previous post: my-point.h and my-point.c. As usual, let's start with the class declaration in the header file. We need to change our declaration macro and add some additional code. For declaration, we will use the following macro:

G_DECLARE_DERIVABLE_TYPE()


As it says, it is used specifically to declare a class that can be further subclassed. It should be noted here, that it is better to use final class by default and use derivable only if it is used for further subclassing. It is always possible to convert a final class to a non-final without breaking ABI but not wise verse. For a derivable class, we need to introduce a class instance structure. The purpose of this structure is to define methods that can be overridden in the derived class. We can view these methods as virtual in the C++ language. The complete header file would be:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef _my_point_h_
#define _my_point_h_

#include <glib-object.h>

#define MY_TYPE_POINT  my_point_get_type ()

G_DECLARE_DERIVABLE_TYPE (MyPoint, my_point, MY, POINT, GObject)

struct _MyPointClass
{
  GObjectClass parent_class;

  void (*move) (MyPoint *obj,
                gint x,
                gint y);
  gpointer padding[12];
};

MyPoint *my_point_new (void);

#endif

Let's take a moment and review what we have here. The _MyPointClass structure should be defined after the G_DECLARE_... macro. It contains a pointer to the function (move). It also contains 12 additional pointers that can be further used for other methods without breaking the ABI. That's it. Now, we can go to our source file and complete the implementation/definition of the object. There are multiple macro available to do so. See the Glib tutorial for the complete list of G_DEFINE_… macro. Here we will use the simplest form the G_DEFINE_.. family:

G_DEFINE_TYPE_WITH_PRIVATE()


For the derivable class, we need also a special private structure instance declared as <object_name>Private and defined in the source file:

1
2
3
4
5
6
typedef struct {
  gint x;
  gint y;
  gchar *name;
  /* stuff */
} MyPointPrivate;

This structure should be defined before the G_DEFINE_TYPE_WITH_PRIVATE() macro. Similar to the final class we also need to define a series of static methods:

my_point_class_init
my_point_init
my_point_dispose
my_point_finalize

We don't need to redefine dispose if we have no references to drop. Similar, we don't need to redefine finalize if no memory should be freed for the class members. Here we do this only to show how it should be done if needed. Our source file, for now, should look like following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include "my-point.h"

typedef struct
{
  gint x;
  gint y;
  gchar *name;
} MyPointPrivate;

G_DEFINE_TYPE_WITH_PRIVATE (MyPoint,my_point,G_TYPE_OBJECT)

MyPoint*
my_point_new (void)
{
  return g_object_new (MY_TYPE_POINT, NULL);
}

static void
my_point_init (MyPoint *self)
{
  MyPointPrivate *priv = my_point_get_instance_private (self);
  priv->x = 1; /* private member initialization */
  priv->name = g_strdup("Hello, world!");
/* All object should be initialized here */
}

static void
my_point_dispose (GObject *object)
{
  MyPoint *self = MY_POINT(object);
  MyPointPrivate *priv = my_point_get_instance_private (self);
/* Drop the references here */
  G_OBJECT_CLASS(my_point_parent_class)->dispose(object);
}

static void
my_point_finalize (GObject *object)
{
  MyPoint *self = MY_POINT(object);
  MyPointPrivate *priv = my_point_get_instance_private (self);
 
  g_free (priv->name);

  G_OBJECT_CLASS(my_point_parent_class)->finalize(object);
}

static void
my_point_class_init (MyPointClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);

  object_class->dispose = my_point_dispose;
  object_class->finalize = my_point_finalize;
}


There is a moment here that differentiates the derivable class implementation from the final one. It is an access to the class members. Now, we can't get access to our class members by dereferencing the object pointer. Instead, we need to create a special instance of our private structure. The following line of code does exactly what we need:

MyPointPrivate *priv = my_point_get_instance_private (self);

After that, any class member can be accessed by dereferencing the private structure instance priv. The function my_point_get_instance_private() we call here is defined by the G_DEFINE_TYPE_WITH_PRIVATE() macro. We don't need to free the memory for priv pointer. Implementation of all methods should be understandable from the part 1. To destroy our class and free memory, we can also call g_object_unref or g_clear_object methods or wrap them into the my_point_free method as we did for the final class.

Now it is time to go back to our class instance structure defined in the header file. We have a pointer move to a function. If we set this pointer to NULL in ..._class_init() method, it will be equivalent to the pure virtual method in the C++ language. The pointer should be set in the derived class. Otherwise, we need to define a default implementation as a static method, e.g.:

1
2
3
4
5
6
7
8
static void
_my_point_real_move (MyPoint *self, gint x, gint y)
{
  MyPointPrivate *priv = my_point_get_instance_private (self);

  priv->x += x;
  priv->y += y; 
}

After that, we can initiate our move pointer to the default implementation by putting

object_class->move = _my_point_real_move;


to the ..._class_init() method. Ok, we initialized our move pointer but how can we call a method to execute the function our move is pointing? We need a public API declared in the header and implemented in the source file. We should add the following code to the header file:

1
 void my_point_move (MyPoint *self, gint x, gint y);

And the definition of this method should look like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
void  
my_point_move (MyPoint *self, gint x, gint y)
{
  g_return_if_fail (MY_IS_POINT(self));

  MyPointClass *klass = MY_POINT_GET_CLASS (self);
 
  g_return_if_fail (klass->move != NULL);

  klass->move(self,x,y); 
}

Let's review what we have her. At line #4 we need to check that self is really a pointer to MyPoint. At line #6 we create an instance for our class, check that our pointer to function is not NULL, at line #8, and call the actual method on line #10. That's it. Now if we call my_point_move(), the method pointed by the move pointer will be executed. In our case it is _my_point_real_move(). To reimplement my_point_move() method in the derived class, we just need to point our move pointer to a different implementation. To do so, we need to create an instance of MyPointClass from the derived class instance in the derived ..._class_init() method and redefine the pointer:

1
2
3
4
5
6
7
static void
my_point_derived_class_init (MyPointDerivedClass *klass)
{
  MyPointClass *pklass = MY_POINT_CLASS (klass);

  pklass->move = _my_point_new_move;
}

The implementation method should have the same signature as the pointer. In our case  - move. If we remove the public API to call our method pointed by the move pointer we will get a private virtual method which can be accessed from the source code only. To make it even more interesting, lets' add two public API to get the class member name and to set it. We need to declare the public API in the header file and implement in the source file. The implementation should be self-explained. We return const gchar* from the .._get_name() because we don't want to modify out class member by the returned pointer. In the next posts, we will see a general approach to handle getters and setters for a class. Now, let's summarize what we have. The header file should be:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef _my_point_h_
#define _my_point_h_

#include <glib-object.h>

#define MY_TYPE_POINT  my_point_get_type ()

G_DECLARE_DERIVABLE_TYPE (MyPoint, my_point, MY, POINT, GObject)

struct _MyPointClass
{
  GObjectClass parent_class;

  void (*move) (MyPoint *obj,
                gint x,
                gint y);
  gpointer padding[12];
};

MyPoint     *my_point_new  (void);
void         my_point_free (MyPoint *self); 

void         my_point_move (MyPoint *self, gint x, gint y);

void         my_point_set_name (MyPoint *self, const gchar *newname);
const gchar *my_point_get_name (MyPoint *self);

#endif

And the source file should be:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "my-point.h"

typedef struct
{
  gint x;
  gint y;
  gchar *name;
} MyPointPrivate;

G_DEFINE_TYPE_WITH_PRIVATE (MyPoint,my_point,G_TYPE_OBJECT)

MyPoint*
my_point_new (void)
{
  return g_object_new (MY_TYPE_POINT, NULL);
}

void
my_point_free (MyPoint *self)
{
  g_clear_object (&self);
}

static void
_my_point_real_move (MyPoint *self, gint x, gint y)
{
  MyPointPrivate *priv = my_point_get_instance_private (self);

  priv->x += x;
  priv->y += y; 
}

static void
my_point_init (MyPoint *self)
{
  MyPointPrivate *priv = my_point_get_instance_private (self);
  priv->x = 1; /* private member initialization */
  priv->name = g_strdup("Hello, world!");
/* All object should be initialized here */
}

static void
my_point_dispose (GObject *object)
{
  MyPoint *self = MY_POINT(object);
  MyPointPrivate *priv = my_point_get_instance_private (self);
/* Drop the references here */
  G_OBJECT_CLASS(my_point_parent_class)->dispose(object);
}

static void
my_point_finalize (GObject *object)
{
  MyPoint *self = MY_POINT(object);
  MyPointPrivate *priv = my_point_get_instance_private (self);
 
  g_free (priv->name);

  G_OBJECT_CLASS(my_point_parent_class)->finalize(object);
}

void  
my_point_move (MyPoint *self, gint x, gint y)
{
  g_return_if_fail (MY_IS_POINT(self));

  MyPointClass *klass = MY_POINT_GET_CLASS (self);
 
  g_return_if_fail (klass->move != NULL);

  klass->move(self,x,y); 
}

void
my_point_set_name (MyPoint *self, const gchar *newname)
{
  MyPointPrivate *priv = my_point_get_instance_private (self);
  g_free (priv->name);
  priv->name = g_strdup(newname);
}

const gchar*
my_point_get_name (MyPoint *self)
{
  MyPointPrivate *priv = my_point_get_instance_private (self);
  return priv->name;
}

static void
my_point_class_init (MyPointClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);

  klass->move = _my_point_real_move;
  klass->dispose = my_point_dispose;
  klass->finalize = my_point_finalize;
}

Thursday, August 16, 2018

Part 1. Deriving from GObject based object.


I remember, when I started my journey in the forest called Glib/GObject [gobject] it was a disaster. I didn't understand basic concepts and had a very hard time to switch my brain from C++ syntax and semantics to Glib style and concepts. Of course, I read tutorial [tutorial] multiple times and was able quickly to recognize where to look what by memorization, but still didn't have an understanding of how to implement an object (final and derivable) or an interface. I was totally confused by a variety of different macro available to declare/define a new object.
In this post, I am not going to retell the Glib manual but will provide my, hopefully, simple and clear, overview of how to start with Glib fearlessly. I found the official Glib documentation very technical and hard to read for new people (I am speaking for myself). Indeed, when you know what you are doing you don't need a tutorial. You need a reference. For beginners, on the other hand, the situation is different. They may come with a different background and experience and tutorial should teach them how to do things in a correct way. The situation becomes even more confused for beginners if they check the existing code in some projects, e.g. GTK+[gtk]. The GObject tutorial [style] encourages to use so-called "modern" way to implement objects but a lot of existing code still contains old style code. I will focus on the new style code here and will not mention the old one.
So let's begin. Here, we will review how to declare and define GObject based object which can be a final object. Let's start with the general file layout. To implement a new object we need two files: header (*.h) and source (*.c). The header file contains a declaration of an object, while the source contains implementation. We should also mention a convention used for file and method naming. All methods for our class will contain a prefix in the format:   <namespace>_<module_name>_. Thus, for the GTK+ namespace would be "gtk", for the GLib project, namespace would be "g".  The "module_name" corresponds to the name of our object. Thus, for class GtkButton the prefix would look like: gtk_button_. The full method name would look like: gtk_button_new(). You got it, right?  See official convention for details [convention].

We will start with the header file "my-point.h". There is a macro available to declare the final class.

G_DECLARE_FINAL_TYPE()


It is used to declare a final object, that can't be used for the following inheritance. It is similar to the following C++ semantic.

class Someclass final
{
};



These type of classes are very common for GUI development using GTK+ widgets. To define the final object "MyPoint" the following header file can be used. The object type, MY_TYPE_POINT in our case, should be defined for every listed above declaration.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#ifndef _MY_POINT_H_
#define _MY_POINT_H_

#include <glib-gobject.h>

#define MY_TYPE_POINT  my_point_get_type ()

G_DECLARE_FINAL_TYPE (MyPoint, my_point, MY, POINT, GObject)

MyPoint *my_pointer_new (void);

#endif


Let's quickly review the arguments we pass to the G_DECLARE_FINAL_TYPE.
arg1: "MyPoint" - a name of the object
arg2: "my_point" - a prefix for our methods
arg3: "MY" - a namespace for our object
arg4: "POINT" - a module name
arg5: "GObject" - a parent class type
That is. Now, we can go to our source file and complete the implementation/definition of the object.  There are multiple macro available to do so. See the Glib tutorial for the complete list of G_DEFINE_… macro. Here we will discuss the most important for us:

G_DEFINE_TYPE()


It is used for a final object that is not planned to be further subclassed.
Now, it is time to think about where we going to keep our private class members. All class members should be stored in the object instance structure. This structure should be defined in the source file and because of that it is not visible for other files, e.g. becomes private:


1
2
3
4
5
6
7
struct _MyPoint
{
  GObject parent_instance;
  gint x;
  gint y;
  gchar *name;
};


The first member should be a parent instance. In our case it is GObject. Pay attention it is not a pointer. The instance structure should be defined before calling G_DEFINE_TYPE_… macro. Putting all together we have:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include "my-point.h"

struct _MyPoint
{
  GObject parent_instance;
  gint x;
  gint y;
  gchar *name;
};

G_DEFINE_TYPE (MyPoint,my_point,G_TYPE_OBJECT)

To correctly initialize our object and class, we need to define two static methods. The should be declared in the source file:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
static void 
my_point_class_init (MyPointClass *klass)
{

}

static void 
my_point_init (MyPoint *self)
{
  self->x = 1;
  self->name = g_strdup("Hello, world!");

/* All other class members should be initialized here */
}

my_point_class_init performs class-wide initialization and executed only once even if you have 100 objects of your class. my_point_init performs initialization of the object instance and executed every time you create a new object of your class. As you can see, we initialized some class member in the instance init method. Now, what about my_point_new() function we declared in the header file? Of course, it should be defined in our source file as a normal (non-static) function:


1
2
3
4
5
MyPoint* 
my_point_new (void)
{
  return g_object_new (MY_TYPE_POINT, NULL);
}

As we can see, the role of my_point_new() method is just to create an instance of our object. The method g_object_new() will invoke all other methods to correctly initialize our class and object instance. It is a  convenient wrapper around g_object_new() method.
Ok, everything looks clear, we can declare an object, define, initialize but what about clean up? A C++ programmer would expect something similar to the destructor.  There are two functions exist in the GObject world to serve the same purpose:

static void my_point_dispose(GObject *object)


and

static void my_point_finalize(GObject *object)


The ..._dispose() method is an entry point for the cleanup process. We need to drop all references to memory that had been passed in through the MyPoint API. In the ..._finilize() function, we should free memory for all private objects we allocated earlier. Both functions should be defined as static and implemented in the source file. We need to call the same dispose and finalize functions for our parent class and every parent class for the parent class should also call these functions. To do so, we should finish the …_dispose() and ..._finalize() methods by calling the same .._dispose() and ..._finalize() methods for the parent object using

G_OBJECT_CLASS (<object_prefix>_parent_class)->dispose (gobject);


and


G_OBJECT_CLASS (<object_prefix>_parent_class)->finalize (gobject);

The .._dispose() method may be called multiple times. The final definition of the ..._dispose() method would look like:


1
2
3
4
5
6
7
static void
my_point_dispose (GObject *object)
{
  MyPoint *self = MY_POINT(object);
/* Drop all references to memory passed in through the object API */
  G_OBJECT_CLASS(my_point_parent_class)->dispose(object);
}

The argument (my_point_parent_class) we pass to G_OBJECT_CLASS macro is defined automatically by G_DEFINE_… macro earlier. We need also point our class to a method it should use for disposing and finalizing processes. It should be done in the class_init method by setting dispose and finalize pointers to point to our methods:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
static void
my_point_dispose (GObject *object)
{
  MyPoint *self = MY_POINT(object);
/* Drop all references to memory passed in through the object API */
  G_OBJECT_CLASS(my_point_parent_class)->dispose(object);
}

static void
my_point_finalize (GObject *object)
{
  MyPoint *self = MY_POINT(object);
  g_free (self->name);
/* Finalize code cleanup */
  G_OBJECT_CLASS(my_point_parent_class)->finalize(object);
}

static void
my_point_class_init (MyPointClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS(klass);
  
  object_class->dispose = my_point_dispose;
  object_class->finalize = my_point_finalize;
}

Of course, if you have no references to clean in ..._dispose() method, it is not necessary to redefine this method. Now, since we have ..._dispose() and ..._finalize() method, how to initiate the object destroy process and free the memory? I personally like to have <prefix>_free() method that can implement correct cleaning and keep API consistent. It should be public as same as <prefix>_new()  and accept our object type as the argument. Thus, we should add the following declaration to the header file:

void my_point_free (MyPoint *obj);


and implement it as follow in the source file:

void my_point_free (MyPoint *obj)
{
  g_clear_object (&obj);
}


Method g_clear_object() is a convenient method to free memory. It clears memory and set object pointer to NULL. Otherwise, standard g_object_unref() can be used for all GObject based classes.

That's it. We can now create a final class derived from the GObject based class using my_point_new() method and destroy it using my_point_free() method. The final header file should be:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#ifndef _MY_POINT_H_
#define _MY_POINT_H_

#include <glib-object.h>

G_BEGIN_DECLS

#define MY_TYPE_POINT  my_point_get_type ()

G_DECLARE_FINAL_TYPE (MyPoint, my_point, MY, POINT, GObject)

MyPoint *my_pointer_new (void);
void my_pointer_free (MyPoint* self);

G_END_DECLS

#endif

And source file would look like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include "my-point.h"

struct _MyPoint
{
  GObject parent_instance;
  gint x;
  gint y;
  gchar *name;
};

G_DEFINE_TYPE (MyPoint,my_point,G_TYPE_OBJECT)

static void
my_point_init (MyPoint *self)
{
  self->x = 1; /* private member initialization */
  self->name = g_strdup("Hello, world!");
/* All object should be initialized here */
}

static void
my_point_dispose (GObject *object)
{
  MyPoint *self = MY_POINT(object);

  G_OBJECT_CLASS(my_point_parent_class)->dispose(object);
}

static void
my_point_finalize (GObject *object)
{
  MyPoint *self = MY_POINT(object);
  g_free (self->name);
/* Finalize code cleanup */
  G_OBJECT_CLASS(my_point_parent_class)->finalize(object);
}

static void
my_point_class_init (MyPointClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS(klass);

  object_class->dispose = my_point_dispose;
  object_class->finalize = my_point_finalize;
}

void
my_point_free (MyPoint *obj)
{
  g_clear_object (&obj);
}

G_BEGIN_DECLS and G_END_DECLS are the convenient macro that help with C++ integration. To be continued.....