GClosure

In GTK 2.0, GClosures are used to represent callbacks supplied by the programmer. It will generally comprise a function of some kind and a marshaller used to call it. In the case of C programs, a closure usually just holds a pointer to a function and maybe a data argument. For a language binding, you will need to develop one or more closure types.

When a GClosure is invoked, its marshal function will be called. As arguments, it will be passed a GValue that the return value should be written into, an array of GValues representing arguments to the function, a context dependent "invocation hint" and an extra data argument:

void marshal(GClosure *closure, GValue *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint, gpointer marshal_data);

Unlike in GTK 1.2, GClosures are extensible and can hold an arbitrary ammount of information, so you won't have to use tricks like passing a pointer to a structure as the user data for a callback.

The most common closure type you will use is one that just wraps a function object from the language you are binding as a GClosure (for use as a signal handler, etc). In the case of interpreted languages, you will probably be able to write a generic closure marshal that will be able to construct arbitrary argument vector when invoking the closure.

The closure marshal would most likely use the GVale -> native type routine written earlier to convert the param_values array into an argument vector suitable for calling the function wrapped by the closure. After calling the closure, the return value can then be converted back to a GValue and stored in return_value.

Creating a New GClosure Type

It is trivial to create a new closure type. First of all you need to decide if you need to store more information in the closure than that provided by the GClosure structure. If so, define a structure to hold the extra data, with a GClosure as the first member. Something like this:

typedef struct _MyClosure MyClosure;
struct _MyClosure {
    GClosure closure;
    /* my extra data goes here */
};

Note that this structure does not need to be in any header files -- it is an implementation detail of your closure. Now to create a closure of this type, use the following statement:

GClosure *closure;

closure = g_closure_new_simple(sizeof(MyClosure), data);

The second argument to g_closure_new_simple gets put in the data member of the GClosure structure. After creating the closure, you can set the extra data members in your custom closure any way you want. If those data members need to be finalised when the closure is freed, then you can add a finaliser to the closure:

static void
my_closure_finalize(gpointer notify_data, GClosure *closure)
{
    MyClosure *myclosure = (MyClosure *)closure;

    /* free the extra data in myclosure */
}

...

g_closure_add_finalize_notifier(closure, notify_data,
                                my_closure_finalize);

If you don't need to pass any extra data to the finaliser, notify_data can be NULL. You can associate a marshal function with the closure with the following command:

g_closure_set_marshal(closure, my_closure_marshal);

In the case where you don't need to store any extra data with the closure, you can simply pass the size of the GClosure structure to g_closure_new_simple and not add any finalize notifiers.

For examples of some closure implementations, see the gobjectmodule.c file in recent pygtk snapshots.