GObject

The new base class for the object system is now GObject (GtkObject is a subclass of GObject now). GObjects are one example of instantiable types in the GType type system. In practice, they are the only instantiable types you will use.

It is important to make the wrapper for this type as good as possible -- it will be the most used wrapper in the binding. The better the GObject wrapper, the more natural the binding will feel.

GObjects are reference counted, so your wrapper should hold a reference to the object, and release it when the wrapper is destroyed. Manipulation of the reference count is done with the following functions:

gpointer g_object_ref(gpointer object);

void g_object_unref(gpointer object);

If you need to associate some data with a GObject, you can use the data APIs:

gpointer g_object_get_data(GObject *object, const gchar *key);

void g_object_set_data(GObject *object, const gchar *key, gpointer data);

void g_object_set_data_full(GObject *object, const gchar *key, gpointer data, GDestroyNotify destroy);

If you are writing a binding for an object oriented language, you will probably want to make a class heirachy of wrappers that correspond to the various GObject subclasses. The functions for each particular GObject type can be mapped to methods on the corresponding wrapper.

At times, you may need to get the type of a particular GObject instance. This can be done with the G_OBJECT_TYPE macro, which effectively has the following prototype:

GType G_OBJECT_TYPE(gpointer object);

As well as creating the various GObject subclasses with their *_new constructors, there is also a generic constructor that can be used for any GObject type. It takes the GType of the object as the first argument, followed by (parameter name, value) pairs, and closed off with a NULL:

gpointer g_object_new(const gchar *first_property_name, ...);

It's use might be something like this:

GtkWidget *widget;

widget = g_object_new(GTK_TYPE_WINDOW,
                      "x", 42,
                      "y", 20,
                      "visible", TRUE,
                      NULL);

The use of g_object_new is the only way to set G_PARAM_CONSTRUCT_ONLY properties on an object. Unfortunately there doesn't seem to be a version of this function that doesn't use C varargs at the moment, which limits its usefulness to language bindings.

Creating GObject Subclasses

In some cases, you may want to create new GObject subclasses from the language binding. For this, you will want to use the g_type_register_static function:

GType g_type_register_static(GType parent, const gchar *type_name, const GTypeInfo *info, GTypeFlags flags);

The GTypeInfo structure passed has the following methods:

typedef struct _GTypeInfo GTypeInfo;
struct _GTypeInfo
{
  /* interface types, classed types, instantiated types */
  guint16                class_size;

  GBaseInitFunc          base_init;
  GBaseFinalizeFunc      base_finalize;

  /* classed types, instantiated types */
  GClassInitFunc         class_init;
  GClassFinalizeFunc     class_finalize;
  gconstpointer          class_data;

  /* instantiated types */
  guint16                instance_size;
  guint16                n_preallocs;
  GInstanceInitFunc      instance_init;

  /* value handling */
  const GTypeValueTable *value_table;
};

In most cases, you will just want to create a new GObject with the same size structure as the parent (or maybe with space for an additional pointer or two). The values to put in the class_size and instance_size members can be derived with the g_type_query function:

void g_type_query(GType type, GTypeQuery *query);

Which returns its data in a GTypeQuery structure:

typedef struct _GTypeQuery GTypeQuery;
struct _GTypeQuery
{
  GType         type;
  const gchar  *type_name;
  guint         class_size;
  guint         instance_size;
};

The base_init and base_finalize members can be left NULL. The class_{init,finalize,data} members can be left NULL in most cases as well. For language bindings, it is probably easier to just initialise signals and properties after registering the type.

What you use for the instance_init function depends on how new types will be instantiated. If the GObject will be created from a wrapper's constructor, then you probably don't want to do anything in the instance_init function, so can leave it as NULL. If you want the wrapper to be created from the GObject's constructor, then you can set instance_init to a function that will construct the wrapper for the object. The first case is what happens in the python bindings.

Putting this all together, the code to derive a GType for a new subclass of GtkWidget might look something like this:

GType typecode;
GTypeInfo type_info = {
    0,    /* class_size */

    (GBaseInitFunc) NULL,
    (GBaseFinalizeFunc) NULL,

    (GClassInitFunc) NULL,
    (GClassFinalizeFunc) NULL,
    NULL, /* class_data */

    0,    /* instance_size */
    0,    /* n_preallocs */
    (GInstanceInitFunc) NULL
};
GTypeQuery query;

g_type_query(GTK_TYPE_WIDGET, &query);
type_info.class_size = query.class_size;
type_info.instance_size = query.instance_size;

/* increase the size of the class or instance structs here if necessary */

typecode = g_type_register_static(GTK_TYPE_WIDGET, "NameOfNewWidget",
                                  &type_info, 0);

It should now be possible to instantiate objects of the new type with g_object_new:

GtkWidget *widget;

widget = g_object_new(typecode, NULL);