GObject is a library that is a base for many other Gnome libraries (like GTK). It is a common base layer providing OOP paradigm to the C language. It may be seen as an alternative to C++ or Objective C, since it enables developers to create classes, but in this case, directly in C (however, in a rather tedious way, since it’s still “just” C)!
GObject is a part of GLib and uses the same version numbers. GLib contains:
- GObject - type system
- GThread - threading
- GIO - I/O operations
Some features of GObject that are often used in GTK apps are:
GObjectroot base type
- signals (like events in .NET)
GObject has been created in the 90s, and the design hasn’t changed much since then. It’s been created before C++ has been standardized (and probably this is why it was even created instead of just using C++).
GObject was originally a part of GIMP Toolkit, which was created for GIMP. Later, GTK was extracted from GIMP to become a standalone thing.
The base type of all types in GTK is
GObject inherits from it). However, we usually use
GObject as a base when we want to
refer to anything in the GTK world, since it implements the core things such as
signals or properties (it’s a bit more complicated than that).
Instances and Classes
GTK types have separate structs for instances and classes, e.g. there is
GObject (instance) and
GObjectClass. The stuff in
GObjectClass is shared
among all GObjects (a list of signals, properties, CSS classes, etc.), while
GObject contains instance-specific data.
Here’s an example of types that we could find in GLib:
The “Thing” and “ThingClass” structs are connected via
So, for example, every instance of
GtkButton will have a pointer to a (common)
GtkButtonClass. There are even macros that allow us to retrieve a
ThingClass from Thing, like
(it’s an equivalent of
There are lots of other macros, some of them just cast one type to another to make the code more readable (plus, they can do some type checks for safety).
Every type in the GObject inheritance tree (also our custom types) needs to be registered. When registering we need to provide a bunch of information:
- what is the size of the instance
- what is the size of the class
- what’s the init function of the instance type
- what’s the init function of the class type
Thanks to the registration, the instantation of the new objects of the registered type will be simplified later on, and it will properly set up the new object using the GObject type system. Otherwise, we’d have to do a bunch of things manually, probably making some mistakes in the process and also making the code completely unreadable.
The registration process requires us to follow some conventions, like creating a
duet of instance and class types that we talked about before (and the class type
needs to have
The registration returns a
The GObject libraries are written in the C language. However, there are a bunch of bindings for many other programming languages that open the toolkit to a vast group of developers. Examples of supported languages include:
Since there are a lot of GObject-based libraries, there is an established way of generating bindings for them - GObject Introspection. The bindings, under the hood, call the C libraries code via mechanisms similar to PInvoke.