Showing posts with label gobject. Show all posts
Showing posts with label gobject. Show all posts

Sunday, January 3, 2016

Few tips about GObject for C++ programmers

While studying NetworkManager code I got more and more comfortable with OO programming retrofitted into C programming language using GObject library. At first I was confused because it is quite complex and I didn't well understand how it works. Furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rmore, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 documentation for beginners is lacking and scare. But, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 more I learned cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 more logical it seemed to me. Since I'm well acquainted with C programming language and to some extent to C++ I decided to write about OO model in GObject, NetworkManager and C based on what someone might expect from C++. As usual, this is for my later reference, but also for everyone else wanting to learn how to use or understand GObject. I'll write in a form of tips, or details you should know in order to better understand how it works.

Declaring a class


In C++ language cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re are two parts of class implementation. First, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a class declaration and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a class definition. Class declaration goes into a header file (e.g. Point.h) and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re you'll find something like this:
class Point {
}
Now, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 question is how to do this in C using GObject? The process is a bit more involved due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 characteristics of a C programming language. Anyway, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 recipe is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following one. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 header file (e.g. point.h) that declares class method you would put cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following code:
#include

#define TYPE_POINT (point_get_type())

typedef struct _PointClass {
    GObjectClass parent_class;
} PointClass;

typedef struct _Point {
    GObject parent_instance;
} Point;

GType point_get_type(void);
This code declares two structures, one that will be used by a class (PointClass) and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r one for each object of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given class type (Point). You would also need to define class and object initialization functions as follows:
#include "point.h"

typedef struct _PointPrivate PointPrivate;

G_DEFINE_TYPE (Point, point, G_TYPE_OBJECT);

static void point_class_init (PointClass* klass)
{
}

static void point_init (Point* self)
{
}
Finally, you can write a main function (in e.g. main.c file) which doesn't do anything, but, nevercá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365less cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class is here. That's how you would declare a class.

The code for this example can be found on GitHub.

Final and derivable classes


The distinction between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two is that you can not subclass final class, while on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r hand, derivable classes can be sub classed. I don't want to go into discussions why final classes, but only into technical details related to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir use in GObject. GObject documentation recommends to use final classes if you can, and only cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n derivable classes. If you take a look at some ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r sources, especially for C++, you'll find doubts about benefits of final classes.

So, in C++ (at least from C++11) you would declare final class like this:
class Point final {
};
Now, if you try to subclass it:
class Point2 : public Point {
};
You'll receive compiler error due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 final keyword prohibiting class Point to be subclassed:
g++ -Wall -std=c++11 main.cpp -o main
In file included from main.cpp:1:0:
Point.h:6:7: error: cannot derive from ‘final’ base ‘Point’ in derived type ‘Point2’
 class Point2 : public Point {
       ^
Note that nothing special has to be done in order for a class to be derivable. Only if you want a class to be final you have to explicitly say so. So, what about GObject and final and derivable classes?

Two macros are used in GObject to create classes for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 purpose of creating final and derivable classes. To define final class use G_DECLARE_FINAL_TYPE macro. You should modify header file from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous example like this:
#include

#define TYPE_POINT (point_get_type())
G_DECLARE_FINAL_TYPE(Point, point, , POINT, GObject)

typedef struct _Point {
    GObject parent_instance;
} Point;
Note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is no definition of type PointClass! The reason is that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 macro G_DECLARE_FINAL_TYPE declares it. Also, point_get_type() isn't declared because G_DECLARE_FINAL_TYPE declares it. That's basically it for final class.

To declare derivable class, macro G_DECLARE_DERIVABLE_TYPE is used. In this case, as in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous, you should only change header file which should look like this:
#include

#define TYPE_POINT (point_get_type())
G_DECLARE_DERIVABLE_TYPE(Point, point, , POINT, GObject)

typedef struct _PointClass {
    GObjectClass parent_instance;
} PointClass;
This time, PointClass type is defined explicitly while Point is defined by G_DECLARE_DERIVABLE_TYPE macro.

The code for this example can be found on GitHub.

Instantiate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object of a given class


The next thing is how would you instantiate an object of some class. For sample, to instantiate an object of a class written in C++ from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous section in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main function you would do cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following:
Point* point = new Point();
To do cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same thing in C/GObject combo, you again have to do a bit more work. Actually, you have to define allocator for a class, i.e. something equivalent to a new keyword in C++. The way to create a new object of a given type is:
Point *point = someclass_new();
So, you need to define cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function someclass_new(). Our will be very simple one:
Point* point_new(void)
{
        return g_object_new(TYPE_POINT, NULL);
}
Place it at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file point.c and in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main function create an object of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Point class by calling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function point_new(). As a final note, instantiating final or derivable class is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same.

The code for this example can be found on GitHub.

Instantiate a singleton object


One feature used by NetworkManager a lot are singleton objects. Namely, some objects control system wide resources and thus cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a need to have a single object control a single resource. For example, main component of a NetworkManager is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object NM_TYPE_MANAGER and it is necessary to have only one such object. There is also a single object for a configuration held in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object/class NM_TYPE_CONFIG.

So, how is singleton object created? NetworkManager has some infrastructure that makes this task really simple. You start with a regular class/object. Then in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 C file with an object implementation you should call cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following two macros/functions:
NM_DEFINE_SINGLETON_INSTANCE (NMNetnsController);
NM_DEFINE_SINGLETON_REGISTER (NMNetnsController);
Then, in function that allocates an object, you have a variable singleton_instance that should be NULL until cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object is created and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n it should contain a pointer to a singleton object. Additionally, after creating object, you should call function nm_singleton_instance_register().

You are tasked with taking care that no new object of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given type is created, i.e. you can shoot yourself in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 foot in case you don't take care to check cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 content of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 variable singleton_instance. singleton_instance is a file global variable declared by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 macros shown above.

Private attributes


The next step is to add private attributes to our class. Let's suppose that we need to add x and y coordinates. In C++ we would modify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class declaration in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following way:
class Point {
private:
        int x, y;
}
And that's basically it for C++ version. In case of C/GObject, you would define struct for private data in C file (point.c) with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following content:
typedef struct _PointPrivate PointPrivate;

struct _PointPrivate {
        int x, y;
};
First, observe that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 structure is placed in C file, not in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 header file. The reason is that this is private/internal structure so no users of a class should know cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 content of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given structure. Furcá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rmore, keep in mode that this structure isn't required to be called as shown in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 example by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 GObject system, you can call it whatever you want, but it is a good practice and strongly suggested to add Private suffix to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object name for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 readability reasons.

Private part for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object should be allocated when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class is initialized. To achieve that add cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following line in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class initialization function, i.e. in point_class_init() function:
g_type_class_add_private (klass, sizeof (PointPrivate));
Before finishing with private attributes, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is one more thing we need to discuss, and that is how to access private part of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object. For that purpose it is good to declare cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following macro:
#define POINT_GET_PRIVATE(object)      \
          (G_TYPE_INSTANCE_GET_PRIVATE((object), TYPE_POINT, PointPrivate))
This macro takes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pointer to an object and returns pointer to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 private data of a given object. Note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last argument to G_TYPE_INSTANCE_GET_PRIVATE is type (structure definition) of a private data. So, when you have a method that accesses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object's private data you would, at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 start of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method, call cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mentioned macro to obtain pointer to private data structure and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n you would access it as usual.

The code for this example can be found on GitHub.

Public methods


After we added private attributes we want to add public methods that will allow us to get and set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 values for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 given private attributes. So, in C++ we would modify Point class definition as follows:
class Point {
private:
        int x, y;
public:
        void setValue(int x, int y);
        int getx(void);
        int gety(void);
};
The public methods should be defined in a C++ file (i.e. Point.cpp):
#include "Point.h"

void Point::setValue(int x, int y)
{
        this->x = x;
        this->y = y;
}

int Point::getx(void)
{
        return this->x;
}

int Point::gety(void)
{
        return this->y;
}
And, obviously, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 methods would be used in a following way in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main function:
point->setValue(1, 1);
std::cout << "x=" << point->getx() << ", y=" << point->gety() << std::endl;
Now, to achieve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same with GObject system several changes to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 existing C code are necessary. First, we'll define a helper macro in a C file (point.c) that we will use to obtain private data of an object of class Point:
#define POINT_GET_PRIVATE(object)      \
          (G_TYPE_INSTANCE_GET_PRIVATE((object), TYPE_POINT, PointPrivate))
Next, public methods are just global functions with a prefix of a object name and with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first argument being cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pointer to an object of a given class. In our case, we have three public methods each with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following prototype:
void point_set_value(Point *point, int x, int y);
int point_get_x(Point *point);
int point_get_y(Point *point);
Those declaration should go into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 header file (point.h) because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are accessible to any user of object Point, while cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir definitions should go into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 C file (point.c):
void point_set_value(Point* point, int x, int y)
{
        PointPrivate* priv = POINT_GET_PRIVATE(point);

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

int point_get_x(Point* point)
{
        PointPrivate* priv = POINT_GET_PRIVATE(point);

        return priv->x;
}

int point_get_y(Point* point)
{
        PointPrivate* priv = POINT_GET_PRIVATE(point);

        return priv->y;
}
Finally, you should use those public methods after object of class Point is allocated in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 main function. Here is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 example:
point_set_value(point, 1, 1);
printf("x=%d, y=%d\n", point_get_x(point), point_get_y(point));
And that's it. The code for this example can be found in GitHub repository.

Virtual methods


The methods implemented using GObject in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous section are non-virtual public methods. They are easy to implement, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 least flexible. So, to implement public virtual methods in GObject we need to:
  1. In class structure (PointClass) add function pointer for each virtual method we need.
  2. In header file declare dispatcher methods that will be called by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class.
  3. Define dispatcher methods in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source file.
  4. Define implementation of virtual methods in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source file.
  5. Initialize function pointers with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation of virtual methods.
Here are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 steps in more details with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 concrete example of Point class. Before continuing, note that virtual methods are possible only in derivable classes, not in final!

Step 1 is to add function pointer fields in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class structure. That means that you class structure definition has to have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following format:
typedef struct _PointClass
{
        GObjectClass parent_class;
        void (*set_value) (Point *self, int x, int y);
        int (*get_x) (Point *self);
        int (*get_y) (Point *self);
} PointClass;
Note cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bold parts, those are function pointer that will point to implementation of virtual methods. Each method takes, as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first argument, pointer to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object it has to act upon.

Step 2 is to declare dispatcher methods. Those are very similar to non-virtual public methods in appearance, i.e. cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 name consists of a object name prefix and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function name. Again, this is recommended, not something that is mandated by GObject system. Anyway, in our case those are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lines you have to add to header file:
void point_set_value(Point* self, int x, int y);
int point_get_x(Point* self);
int point_get_y(Point* self);
Step 3 is to define dispatcher methods in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source file. I'll do it only for one method, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 rest are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same. So, in case of point_set_value() it would look like this:
void point_set_value(Point* self, int x, int y)
{
PointClass *klass;
klass = _POINT_GET_CLASS(self);
klass->set_value(self, x, y);
}
As you can see, what cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method does is it access class definition, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n invokes appropriate function through its pointer. I have to stress here two things:
  1. I skipped assertions, i.e. if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object/classes are of right type!
  2. Note cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 leading underscore in _POINT_GET_CLASS. It is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 consequence of skipping module name when calling G_DECLARE_DERIVABLE_TYPE macro, i.e. I skipped third argument!
So, any user of a class will call those public methods which will dispatch cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 real method.

In step 4 we have to define implementation of virtual methods in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source file. Again, I'll show it only for a single method. Also, you'll note that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 implementation is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same as for non-virtual public methods. Only we have to call cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m differently so that compiler can differentiate between different function. I decided to use prefix objectname_private_, but it is my choice. I didn't manage to find something recommended by GObject. So, here it goes for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function to set value:
void point_private_set_value(Point* self, int x, int y)
{
PointPrivate *priv = POINT_GET_PRIVATE(self);
priv->x = x;
priv->y = y;
}
Finally, step 5 is to initialize pointers to dispatchers which in turn will call real methods. This has to be done by modifying definition of PointClass structure (or class structure in general). Here is how this structure should look like:
static void
point_class_init (PointClass* klass)
{
g_type_class_add_private (klass, sizeof (PointPrivate));
klass->set_value = point_private_set_value;
klass->get_y = point_private_get_y;
klass->get_x = point_private_get_x;

}
Note that we have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 part that adds private data for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 objects. The bold parts are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ones that initialize virtual functions.


Inheritence and subclassing


Inheritance allows for specialization of some class without touching that class internals. It is one of very important OO mechanisms and as such it is also supported in GObject and used by, e.g. NetworkManager.

So, suppose we want to define 3D point by basing its implementation on Point class while in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same time adding only z coordinate. In C++ we would declare new class and say explicitly that we inherit base class Point:
#include "Point.h"

class Point3D: public Point
{
private:
        int z;
public:
        void setValue(int x, int y, int z);
        int getz(void);
}
As you can see we include declaration of 2D point and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n we add third coordinate as well as new methods, one to retrieve cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 third coordinate and anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r one to be able to set all three coordinates. There is also definition (i.e. implementation) of a new class which is placed in Point3D.cpp file:
#include "Point3D.h"

void Point3D::setValue(int x, int y, int z)
{
        Point::setValue(x, y);
        this->z = z;
}

int Point3D::getz(void)
{
        return this->z;
}
Note how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base class method is called, by prefixing cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 method name with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base class name.

As usual, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 question is how this is done in C using GObject library. First, GObject make distinction between final and derivable classes, as we already saw above. Base class must be derivable, while subclass might be eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r final or derivable.

So, we are going to define derivable class Point as follows:
#include

#define TYPE_POINT (point_get_type())
G_DECLARE_DERIVABLE_TYPE(Point, point, , POINT, GObject)

typedef struct _PointClass {
        GObjectClass parent_class;
} PointClass;

Point* point_new(void);

void point_set_value(Point *point, int x, int y);
int point_get_x(Point *point);
int point_get_y(Point *point);
This is almost cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same as original Point declaration we had. The implementation part isn't changed. Now, Point3D is declared as follows:
#include
#include "point.h"

#define TYPE_POINT3D (point3d_get_type())
G_DECLARE_FINAL_TYPE(Point3D, point3d, , POINT3d, Point)

typedef struct _Point3D {
        Point parent_instance;
} Point3D;

Point3D* point3d_new(void);

void point3d_set_value(Point3D* point, int x, int y, int z);
int point3d_get_z(Point3D* point);
Note cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last parameter in G_DECLARE_FINAL_TYPE is Point. Basically, that's cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 base class and up until now we had cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re GObject from which all object descend.

Defining and implementing interfaces


Interfaces in OO languages are used as a form of a contract between different components. Some languages, as Java for example, have direct support for defining interfaces, while ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rs, like C++, don't have and instead use some indirect methods. Here I would like to show how interfaces are implemented in GObject and for that purpose I'll declare interface that will be implemented by Point class used so far for examples. We'll start with C++, as usual.

To define interface in C++ abstract classes are used. Abstract class can not be instantiated because it has at least one pure virtual method that needs to be implemented by subclass. So, here is how interface for Point class would look like in C++:
class PointInterface {
public:
virtual void setValue(int x, int y) = 0;
virtual int getx(void) = 0;
virtual int gety(void) = 0;
};
As you can see, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 pure virtual method is declared by having "equal zero" addition. Now, just one more change is necessary and that is to declare that Point class implements this interface/abstract class. To do that only a single change is necessary, i.e.:
class Point : public PointInterface { ... }
In ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r words, Point inherits PointInterface.

So, how to do this in GObject? Here is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 official documentation and we are going to do this for our existing Point class.

TBC...

Constructor


In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous examples we already saw constructors, class constructor (*_class_init) and object constructor (*_init). Class constructor is called only once, when a first object of a given class is instantiated. Object constructor, on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r hand, is called every time an object of a given class is instantiated. You can easily see this modifying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous example so that you place printf() statements into appropriate constructors (point_class_init() for a class constructor and point_init() for an object constructor). Then, by creating two objects of a Point class you'll clearly see that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class constructor is called only once, while cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 object constructor is called as many times as you instantiated objects.

Destructor


Destructor isn't necessary



Object/class initialization and removal

When creating a new object using g_object_new() function cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is a certain sequence of steps executed. For an object that is first of its class, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sequence is:

  1. _class_init()
  2. constructor()
  3. constructed()
  4. _init()

Of those four, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first and fourth, are mandatory and have to be defined in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 source. The second and third steps are optional and you define cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m in class constructor (_class_init()) by assigning appropriate pointers to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 class interface.

Note that g_object_new() accepts an object type that should be created and a sequence of attribute-value pairs terminated with a single NULL. Those attribute-value pairs are used to set properties of an object (installed using g_object_class_install_property() function) but only after object constructor finishes. Also, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 additional requirement is to define set_property class method that will be called to set each property.

For objects of next type only object constructor is called and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n properties are initialized.

When object is removed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n its destructor is called, if it exists. If this is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 last object of its class, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n finalize method is called, again, if it exists.

Name spaces


TBD


Literature

If you try to Google for GObject examples or tutorials you'll find some materials from Gnome Web site. But, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 truth is that those tutorials leave some open questions and it is really hard to find something else. In cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 end I managed to find some references that I think are very valuable so here cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are:

About Me

scientist, consultant, security specialist, networking guy, system administrator, philosopher ;)

Blog Archive