GObject消息系统:Closure (转)

os posted @ 2013年8月24日 13:16 in GObject , 1067 阅读

Closures

Closures是异步信号传递概念的中心,它被广泛的应用到了GTK+和GNOME应用程序中。一个Closure是一个抽象的、通用表示的回调(callback)。它是一个包含三个对象的简单结构:

  • 一个函数指针(回调本身) ,原型类似于:return_type function_callback (... , gpointer user_data);
  • user_data指针用来传递到callback在调用Closure时。
  • 一个函数指针,代表Closure的销毁:当Closure的引用数达到0时,这个函数将被调用来释放Closure的结构。

GClosure结构代表所有Closure实现的共同基础:现在存在着很多各自不同的使用GObject类型系统的运行环境。GObject库提供一个简单的GCClosure类型,来明确使用C/C++的回调来实现。

一个GClosure提供以下简单的服务:

  • 调用(g_closure_invoke):这就是Closure创建的目的: 它们隐藏了回调者的回调细节。
  • 通知:相关事件的Closure通知监听者如Closure调用,Closure无效和Clsoure终结。监听者可以用注册g_closure_add_finalize_notifier(终结通知),g_closure_add_invalidate_notifier(无效通知)和g_closure_add_marshal_guards(调用通知)。对于终结和无效事件来说,这是对等的函数(g_closure_remove_finalize_notifier和g_closure_remove_invalidate_notifier,但调用过程不是。

 

C Closures

如果你用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函数如果用户提供过的话。

non-C closures (for the fearless)

我们在前面提到过,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对象。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter