The GTK+ Object and Type System

Table of Contents
Object and Class Structures
Type Checking and New Types
Initializing a New Class
GtkArg and the Type System
Object Arguments
Object Finalization
Attaching Data to Objects

People often ask why GTK+ was written in C rather than an object-oriented language. The answer is that C is more portable and standardly available than any other language. However, although C lacks syntactic sugar for object-oriented programming, it in no way prohibits an object-oriented approach.

GTK+ implements its own custom object system, which offers standard object-oriented features such as inheritance and virtual functions. In the tradition of languages such as Lisp, Smalltalk, and Java, the GTK+ object system is more runtime-centric than that of C++, allowing interpreted language bindings and GUI builders to interact with it in powerful ways.

You may recall from the chapter called GTK+ Basics that widgets are a special type of GtkObject; any object with GtkWidget in its ancestry is a widget. Widgets represent a region on the screen---most of them are user interface elements, such as buttons or menus. There's nothing GUI-specific about GtkObject; the object system can be used in non-graphical programs.

This chapter dives right into the details of GTK+'s object system, giving you an idea what's happening "behind the scenes" in any GTK+ program. Sooner or later you'll need this information: to write your own objects, debug existing objects, or just understand GTK+ code on a conceptual level.

Object and Class Structures

Each GtkObject has two essential components: a struct representing an instance of the object, and a struct representing the class. In general, the instance struct contains the data members for each instance, and the class struct contains class function pointers (which can be overridden by subclasses). The class struct can also contain class data members---however, it's more typical to use static variables in the .c file implementing the object. If you're familiar with C++, the class struct is equivalent to a vtable, only the class struct is written by hand. It stores virtual functions for an object type.

Here are the structs used in GtkButton:

typedef struct _GtkButton       GtkButton;
typedef struct _GtkButtonClass  GtkButtonClass;

struct _GtkButton
  GtkBin bin;

  GtkWidget *child;

  guint in_button : 1;
  guint button_down : 1;
  guint relief : 2;

struct _GtkButtonClass
  GtkBinClass        parent_class;
  void (* pressed)  (GtkButton *button);
  void (* released) (GtkButton *button);
  void (* clicked)  (GtkButton *button);
  void (* enter)    (GtkButton *button);
  void (* leave)    (GtkButton *button);

Notice that the first member of struct _GtkButton is GtkBin---that's because GtkButton is a subclass of GtkBin. (GtkBin is a GtkContainer that can hold one child.) Since GtkBin is the first member, we can safely cast a GtkButton to GtkBin. In struct _GtkButtonClass, the same principle applies, and GtkBinClass is the first member.