Closures是异步信号传递概念的中心,它被广泛的应用到了GTK+和GNOME应用程序中。一个Closure是一个抽象的、通用表示的回调(callback)。它是一个包含三个对象的简单结构:
GClosure结构代表所有Closure实现的共同基础:现在存在着很多各自不同的使用GObject类型系统的运行环境。GObject库提供一个简单的GCClosure类型,来明确使用C/C++的回调来实现。
一个GClosure提供以下简单的服务:
如果你用C或C++来通过一个给定的事件来连接一个回调,你可以选择使用一个简单的GCClosures来拥有一个完美又小的API或者使用更简单的g_signal_connect函数(后面将讲这个):
GClosure* g_cclosure_new (GCallback callback_func,
gpointer user_data,
GClosureNotify destroy_data);
GClosure* g_cclosure_new_swap (GCallback callback_func,
gpointer user_data,
GClosureNotify destroy_data);
GClosure* g_signal_type_cclosure_new (GType itype,
guint struct_offset);
g_cclosure_new将创建一个新的closure将创建一个调用用户提供的回调函数,用户提供的user_data作为一个最后的参数。当closure被终结后(销毁的第二步),它将调用destroy_data函数如果用户提供的话。
g_cclosure_new_swap将创建一个closure来调用用户提供的回调函数使用用户提供的用户数据作为第一个参数(用来取代第用g_cclosure_new创建的最后一个参数)。当closure被终结后(销毁的第二步),它将调用destroy_data函数如果用户提供过的话。
我们在前面提到过,Closure隐藏了回调请求的细节。在C语言中, 回调请求就像是函数调用:它在堆栈上为被调用的函数创建正确的框架并执行一个呼叫说明。
C Closure 转换目标函数中代表参数的GValue数组为C语言式的参数列表,用这新的参数列表来调用C函数,得到函数的返回值,并将其转换为一个GValue并将其返回给呼叫者。
下面的代码用C实现了一个简单的C函数,用整型作为它的第一个参数,并返回空值。
g_cclosure_marshal_VOID__INT (GClosure *closure,
GValue *return_value,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data)
{
typedef void (*GMarshalFunc_VOID__INT) (gpointer data1,
gint arg_1,
gpointer data2);
register GMarshalFunc_VOID__INT callback;
register GCClosure *cc = (GCClosure*) closure;
register gpointer data1, data2;
g_return_if_fail (n_param_values == 2);
data1 = g_value_peek_pointer (param_values + 0);
data2 = closure->data;
callback = (GMarshalFunc_VOID__INT) (marshal_data ? marshal_data : cc->callback);
callback (data1,
g_marshal_value_peek_int (param_values + 1),
data2);
}
当然,还存在其他形式的调用。比如,James Henstridge写了一个通用的Python marshaller,用在所有的Python Closure上(一个Python Closure就是closure调用过程中,使其拥有一个基于Python的回调)。这个python marshaller转换输入的代表函数参数的GValue列表到一个Python的等价结构的tuple(你可以在GNOME CVS服务器上查看pygobject结构的源码pygtype.c看到pyg_closure_marshal)
实际应用中,Closure是用来设定语言运行时的边界:如果你正在写Python代码,并且某个Python回调函数收到了一个GTK+控件的信号,所以GTK+的C代码需要执行Python代码。由GTK+对象调用的Closure将调用Python的回调:它的行为就是GTK+的C对象,也是一个标准的Python代码的Python对象。