Signals in GObject are used to support a event-driven programming. Signals can be connected to callback handlers. When they are emitted, these handlers are invoked. To add signals to a type, notice following lines of code:

NOTE: PLEASE READ ALL COMMENT CAREFULLY.

Like properties, signals can be inherited too. Use signals like:

The callback functions are defined simply like:

All source code is available in my skydrive: http://cid-481cbe104492a3af.office.live.com/browse.aspx/share/dev/TestOO. In the TestGObject-{date}.zip/TestGObject5 folder.

Properties are supported by the GObject library. To use it, you should override the set_property() and get_property() function in GObjectClass:

NOTE: PLEASE READ ALL COMMENT CAREFULLY.

All APIs are clear and easy to use, please refer to the official document. Last but not least, properties can be inherited by derived classes. Here’s my test code:

As you see, we can get/set properties one by one or using a parameter list.

All source code is available in my skydrive: http://cid-481cbe104492a3af.office.live.com/browse.aspx/share/dev/TestOO. In the TestGObject-{date}.zip/TestGObject5 folder.

Here’s some trivial note on using GObject library.

1. Private members

Recall our definition of Base type:

NOTE: PLEASE READ ALL COMMENT CAREFULLY.

It expose the visibility of base_instance_i field. We should keep encapsulation in OOP. GObject library has support for this. We can define the class as:

We declare a new FakeBasePrivate struct to contain all private field used in FakeBase type. And the private struct is defined in *.c file, so its internal representation remains invisible. Then in *.c file, we got:

The private member is malloc in class_init() callback, and is ready to use after invoking instance_init(). When we will use property mechanism to get/set these private field later.

2. Naming convention

Official document: http://library.gnome.org/devel/gobject/stable/gtype-conventions.html. Just follow it to make your code more readable.

All source code is available in my skydrive: http://cid-481cbe104492a3af.office.live.com/browse.aspx/share/dev/TestOO. In the TestGObject-{date}.zip/TestGObject5 folder.

Now, we will begin to implement some real OO mechanism using GObject library. In this article, we will make our fundamental type Inheritable.

Here’s comes our Base type:

NOTE: PLEASE READ ALL COMMENT CAREFULLY.

In base_instance_init(), we assigned the base_instance_dump() callback. Thus, we can invoke this function by both global function or instance function of BaseClass class. Additional flags G_TYPE_FLAG_DERIVABLE and G_TYPE_FLAG_DEEP_DERIVABLE are also passed to the GTypeFundamentalInfo struct to enable inheritance.

It’s time to define our Derived type:

Our Derived type inherits Base by replacing GTypeClass and GTypeInstance with the corresponding struct of the Base type. According to the memory layout of structs, GTypeClass and GTypeInstance are still the first member of corresponding struct. In derived_get_type(), we register Derived type using g_type_register_static() since it’s not a fundamental at all. And the first parameter is the type id of Base type.

Let’s have some time to look up how to implement polymorphism. In derived_class_init(), we re-assign the base_instance_dump() callback to from the Base‘s implementation to Derived‘s implementation.

Test code:

All source code is available in my skydrive: http://cid-481cbe104492a3af.office.live.com/browse.aspx/share/dev/TestOO. In the TestGObject-{date}.zip/TestGObject4 folder.

We will make fundamental type instantiatable and complete our first usage sample in this article. An object class should be defined firstly:

NOTE: PLEASE READ ALL COMMENT CAREFULLY.

Also, we re-define the class struct:

GTypeClass should be the first member of a class struct, while TypeInstance the first member of a object struct. You may wonder why there’s two int variable in both struct. The foo_class_i is like a static variable in C++ class, while The foo_instance_i is like an instance variable in C++ class. And remember fields in a class struct? It is used as meta info.

The registry function also need modification:

We assigned the instance_init() callback. It is called when a instance of our Foo class is created. You may ask where is the corresponding instance_finalize() callback? Hey, we will discuss it in upcoming articles. The instance_init() callback can be regarded as the constructor of a C++ class. Note, an additional G_TYPE_FLAG_INSTANTIATABLE flag is also added in the GTypeFundamentalInfo struct.

Let’s see how to create an instance:

Congratulations! You’ve finished the learning of our fundamental sample.

All source code is available in my skydrive: http://cid-481cbe104492a3af.office.live.com/browse.aspx/share/dev/TestOO. In the TestGObject-{date}.zip/TestGObject3 folder.