Recall there are 3 types in GObject type system: Fundamental, static and dynamic. A fundamental type is a top-most type which has no parent type. Most of them are pre-defined. Static types never load/unload its class type (say, their class struct) at runtime, since they are static. On the contrary, dynamic types can be dynamically loaded/unloaded at runtime. They are normally used within a module.

We can call g_type_register_dynamic() to register a dynamic type. When used in a module of GObject library (may be a GTypeModule type), We can also call g_type_module_register_type() to create your dynamic types. g_type_register_dynamic() is invoked for you in that function. Let’s go through the code:

NOTE: PLEASE READ ALL COMMENT CAREFULLY.

The implementation structure may be a little different with the stuff when creating a static type. An additional parameter GTypeModule is passed in. It represents the module your dynamic type belongs to. So, when the module is unloaded, all dynamic types in it are unaccessible.

Also note the bar_type_class_finalize() function. We use it to override the finalize() virtual function in GObjectClass. Now you can do un-initialiation in this function. It is like the destructor in a C++ class.

Let’s move on to the module type. This type inherits GTypeModule:

GTypeModule is an abstract type. We should implements its load() and unload() virtual function.

Our test code:

Another dynamic type BarType is defined in addition to FooType to demo the usage. The output maybe:

See the init/finalize process?

At the end of my note, Let me summarize to compare GObject library with C++ implementation:

1. Member Variables:

GObject C++
in class struct class meta info
in object struct class instance member
global variable class static member

2. Function Callbacks:

GObject C++
base_init init class dynamic meta info
base_finalize finalize dynamic class meta info, only dynamic types use it
class_init init class static meta info
class_finalize finalize class static meta info, only dynamic types use it
instance_init init instace, like C++ constructor
override finalize in GObjectClass finalize instance, like C++ destructor

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

Interfaces usage in library is like class usage. We need to define a interface struct, but no object struct is needed:

NOTE: PLEASE READ ALL COMMENT CAREFULLY.

Then we register the interface using g_type_register_static() with G_TYPE_INTERFACE as first parameter. For interfaces, we only need to assign base_init() and base_finalize()callbacks.

As described in the official document, we should allocate dynamic memebers of class struct in base_init(). Otherwise, all copies of the class struct share only one copy of dynamic members. This leads to problems.

Let’s define the type which implements the interface:

Note the naming convention I used here. Our FakeDesktop class will implement the FakeIServer interface and another FakeIClient interface. This time do not use corresponding interface struct as the first members of FakeDesktop and FakeDesktopClass. Interface info will be added dynamically when initialize a real instance of FakeDesktop. Let’s move to the *.c code:

Note the g_type_add_interface_static() function call to add interface info. The interface info is defined in a GInterfaceInfo struct. We just make use of the interface_init() callback. In it, we assign function pointers of corresponding interface to our implementation function. We can add multiple interface infos to implement them.

Finally, the test code:

In runtime, if your classed type implements an interface, it will be considered as the interface type (is-a).

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

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.