http://nanjingabcdefg.is-programmer.com/posts/24116.html
红色部分为自己加的注释
在GObject中,如果想给自己写的类加上signal,一般需要在*_class_init函数中使用g_signal_new函数,但是这个函数的参数比较复杂:
1
2
3
4
5
6
7
8
9
10
|
guint g_signal_new(
const
gchar *signal_name,
GType itype,
GSignalFlags signal_flags,
guint class_offset,
GSignalAccumulator accumulator,
gpointer accu_data,
GSignalCMarshaller c_marshaller,
GType return_type,
guint n_params,
...);
|
从该函数的原型中,我们可以看出,该函数的参数个数是可变的。
下面,我姑妄从前往后依次解释一下各个参数的含义:
在实际使用过程中,该回调函数的类型(指参数和返回值)好像无所谓,都能被调用到。无法传递参数给该回调函数。使用g_signal_connect注册的回调函数的调用顺序先于该回调函数。
1
2
3
4
|
typedef
gboolean (*GSignalAccumulator) (GSignalInvocationHint *ihint,
GValue *return_accu,
const
GValue *handler_return,
gpointer data);
|
1
2
3
4
5
|
typedef
struct
{
guint signal_id;
GQuark detail;
GSignalFlags run_type;
} GSignalInvocationHint;
|
其中,signal_id是导致GSignalAccumulator所指函数被调用的signal的ID(因为该信号signal调用了某个handler)。detail是该signal的detail部分对应的GQuark(其实就是字符串的散列值)。run_type则反映了handler被调用时signal发射进行到的阶段,其值为 G_SIGNAL_RUN_FIRST,G_SIGNAL_RUN_LAST或G_SIGNAL_CLEANUP。
显然,该函数的返回类型为gboolean。如果其返回值为FASLE,则signal发射过程就会被中止(即不再调用后面的hander),否则会继续下去。事实上,"delete-event"等带有event后缀的signal就是利用了这一点——这些信号的某个回调函数如果返回了TRUE,则以后的回调函数就不会被调用。
我们可以看一下"delete-event"的accumulator, _gtk_boolean_handled_accumulator的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
gboolean
_gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const
GValue *handler_return,
gpointer dummy)
{
gboolean continue_emission;
gboolean signal_handled;
signal_handled = g_value_get_boolean (handler_return);
g_value_set_boolean (return_accu, signal_handled);
continue_emission = !signal_handled;
return
continue_emission;
}
|
注意,如果该signal有accumulator,该signal的回调函数类型(由c_marshaller反映)必须有返回值,否则该signal不能有accumulator,也即在调用g_signal_new时以NULL作为该形参的实参。
例如,g_closure_marshal_VOID_VOID说明该signal的回调函数为以下的callback类型:
typedef void (*callback) (gpointer gobject, gpointer user_data);
而g_closure_marshal_VOID_POINTER则说明该signal的回调函数为以下的callback类型:
typedef void (*callback) (gpointer gobject, gpointer arg1, gpointer user_data);
如果默认提供的GClosureMarshall中没有你需要的,你可以用glib-genmarshall生成它,具体可参见devhelp中有关glib-genmarshall的说明。
最后,我们来解释一下GSignalFlags中各个特征标志的含义:
例子请看cloverprice的文章:《GObject 08: A class with a signal》
传送门:http://cloverprince.javaeye.com/blog/500964
注:信号的发射以我的理解,就是按照要求调用回调函数的过程……