在GObject中,如果想给自己写的类加上signal,一般需要在*_class_init函数中使用g_signal_new函数,但是这个函数的参数比较复杂:
从该函数的原型中,我们可以看出,该函数的参数个数是可变的。
下面,我姑妄从前往后依次解释一下各个参数的含义:
-
const gchar
*signal_name:该参数是信号的名字,由分隔符以及ASCII码中的字母和数字构成,并且第一个字符必须是字母。分隔符可以是"-"或"_"
——事实上,系统会先调用g_strdelimit把"_"转化为"-"再存储signal_name。因此,在调用
g_singal_emit_by_name时,detailed_signal参数中的分隔符必须是"-"。
-
GType itype:该参数是signal所依附的类的在GType类型系统中注册时得到的ID,也就是*_get_type()函数的返回值。
-
GSignalFlags signal_flags:该参数是信号的属性标记,有七种,我将在最后解释:
-
G_SIGNAL_RUN_FIRST
-
G_SIGNAL_RUN_LAST
-
G_SIGNAL_RUN_CLEANUP
-
G_SIGNAL_NO_RECURSE
-
G_SIGNAL_DETAILED
-
G_SIGNAL_ACTION
-
G_SIGNAL_NO_HOOKS
-
guint
class_offset:该参数是itype对应的类的class结构中的一个函数指针相对于class结构的实例的首地址的偏移量。该函数指针所对应
的函数常被称为"per-object handler","default (signal) handler"或"object methond
handler",并将在信号发出后被调用(如调用g_signal_emit_by_name)。常配合宏G_STRUCT_OFFSET使用(该宏能
够返回结构体变量的成员相对于该结构体的变量的首地址的偏移量)。如果设为0,则表示该类没有"per-object handler"。
-
GSignalAccumulator accumulator:该参数是一个函数指针,其对应的函数将在该信号的每个handler执行完以后执行。GSignalAccumulator类型的定义如下:
从中可以看出该函数指针类型有4个参数:
-
GSignalInvocationHint *ihint:该参数是一个GSignalInvocationHint类型的指针,而GSignalInvocation结构的定义如下:
-
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。
-
GValue *return_accu:该参数是一个GValue类型的指针,可以被程序员用来返回任何在GType类型系统注册的,带有value_table的类型。
-
const GValue
*handler_return:该参数是一个GValue类型的指针,指向一个GValue变量,该变量存储了GSignalAccumulator所
指函数被调用前,信号调用的handler的返回值,可以用g_value_get_*系列函数获取其存储的值。
-
gpointer data:该参数即为g_signal_new的参数gpointer accu_data的值
显然,该函数的返回类型为gboolean。如果其返回值为FASLE,则signal发射过程就会被中止(即不再调用后面的hander),否则会继续
下去。事实上,"delete-event"等带有event后缀的signal就是利用了这一点——这些信号的某个回调函数如果返回了TRUE,则以后
的回调函数就不会被调用。
我们可以看一下"delete-event"的accumulator, _gtk_boolean_handled_accumulator的代码:
-
gpointer accu_data:该参数将作为用户自定义参数传入accumulator所指向的函数中。
-
GSignalCMarshaller
c_marshaller:该参数是一个GSignalCMarshall类型的函数指针,其值反映了回调函数的返回值类型和额外参数类型(所谓“额外参
数”,即指除回调函数中instance和user_data以外的参数)。
例如,g_closure_marshal_VOID_VOID说明该signal的回调函数为以下的callback类型:
typedef void (*callback) (gpointer instance, gpointer user_data);
而g_closure_marshal_VOID_POINTER则说明该signal的回调函数为以下的callback类型:
typedef void (*callback) (gpointer instance, gpointer arg1, gpointer user_data);
如果默认提供的GClosureMarshall中没有你需要的,你可以用glib-genmarshall生成它,具体可参见devhelp中有关glib-genmarshall的说明。
-
GType return_type:该参数的值应为回调函数的返回值在GType类型系统中的ID。
-
guint n_params:该参数的值应为回调函数的额外参数的个数。
-
...:这一系列的参数的值应为回调函数的额外参数在GType类型系统中的ID,且这一系列参数中第一个参数的值为回调函数的第一个额外参数在GType类型系统中的ID,依次类推。
最后,我们来解释一下GSignalFlags中各个特征标志的含义:
-
G_SIGNAL_RUN_FIRST:调用回调函数时,"per-object handler"对应的回调函数将第一个调用
-
G_SIGNAL_RUN_LAST:调用回调函数时,"per-object handler"对应的回调函数将在用户用g_signal_connect连接的回调函数之后调用,并在用户用g_signal_connect_after连接的回调函数之前调用
-
G_SIGNAL_RUN_CLEANUP:调用回调函数时,"per-object handler"对应的回调函数将最后一个调用
-
G_SIGNAL_NO_RECURSE:信号发射时,如果信号的上次发射还没有结束,那么本次信号发射将不再进行,而只是使上次的信号发射重新开始。
-
G_SIGNAL_DETAILED:信号名字可以使用"signal_name::detailed"的形式。
-
G_SIGNAL_ACTION:程序员可以在代码中自由地调用g_signal_emit族的函数来发射信号,而不需要把g_signal_emit族的函数放在一段代码中再来调用。
-
G_SIGNAL_NO_HOOKS:信号发射过程中不支持钩子函数。
例子请看cloverprice的文章:《GObject 08: A class with a signal》
传送门:http://cloverprince.javaeye.com/blog/500964
阅读(2154) | 评论(0) | 转发(0) |