转载请注明出处www.cnblogs.com/pingf或 blog.csdn.net/pingf0
好久没写这方面的东西了,觉得生疏了不少,主要最近逼着整了点JAVA
继续前面的总结
这一部分将记录一些关于GObject中的信号机制
在开始之前,应该先明白几个概念
closure
callback
marshaller
accumulator
具体来看一看
typedef struct {
volatile guint in_marshal : 1;
volatile guint is_invalid : 1;
} GClosure;
typedef struct {
GClosure closure;
gpointer callback;
} GCClosure;
void (*GClosureMarshal) ( GCClosure *closure,
GValue *return_value,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
估计没有了解过GObject的人一看会有些晕,而像我这般了解了一点点的看起来也晕
实际上我都不知该怎么翻译Closure了,好像一些更高级的语言把这个词称为闭包,但显然此处是另外一个概念。
准确说应该跟回调(callback)相似
Gclosure就是普通的Closure,而GCClosure是针对C语言的
可以看到普通只是定义了两个标志位,而针对C语言的又增加了一个回调指针。
虽然细节还不清楚,但大致应该能明白了,其实Closure的用途就是回调而已。
而所谓marshal 从字面理解就是编组,下面谈一下个人目前的理解
在GObject中有一些类似GValue的形态,在回调时,
通过marshal函式来确定传递数据的具体类型(比如C中的int char等),
当然其实通过它也确定了回调函式的类型
最后是accumulator ,它也是一个函式指针,只不过在每个closure执行后执行,用来处理收尾工作的
好,关于信号部分的预备知识就介绍到这里,如果你不明白,那也别问我了(因为你要问我也不明白)
下面开始正题
所谓信号其实就是通过“触发”,来进行特定的处理
(其实个人觉得还是直接再调用函式,只是调用的方法有点迷惑人罢了)
我们定义信号时要定义具体的信号标识(guint型),并向GObject系统注册,注册时可以指定一字符串,
这样使用起来更方便
enum { JC_BOY_PLAY, JC_BOY_LAST_SIGNAL };
static guint jc_boy_signals[JC_BOY_LAST_SIGNAL] = { 0 };
下面这个应在class的init函式中使用
jc_boy_signals[JC_BOY_PLAY] =
g_signal_new ("play", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (JcBoyClass, play), NULL, NULL,
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
p.s.常见的注册形式有 g_signal_new和 g_signal_newv两个函式
"play"是信号名
G_SIGNAL_RUN_LAST 是信号标识,可以通过对其的设定,改变调用的顺序
G_STRUCT_OFFSET (JcBoyClass, play)用来设定触发时默认的调用
NULL位置的参数与accumulator有关,一般不用
g_cclosure_marshal_VOID__VOID 指定了回调函式的类型,其定义如下
void g_cclosure_marshal_VOID_VOID (GClosure *closure,
GValue *return_value,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
它对应的回调函式是void (*callback) (gpointer instance, gpointer user_data)
.
而g_cclosure_marshal_VOID__BOOLEAN ()则对应
void (*callback) (gpointer instance, gboolean arg1, gpointer user_data)
.
G_TYPE_NONE 用来指定返回参数的类型,此处表示没有返回
最后的0为终止标识,在此之前如有需要,应增加传入的参数
上面默认的调用可以为如下例子
static void play(JcBoy *self)
{
gchar *play;
g_object_get(G_OBJECT(self),"hobby",&play,NULL);
g_print("the boy is %s\n",play);
}
p.s.上面代码展示了如何通过GObject获取字符串类型的属性
信号的发射
g_signal_emit_by_name(self,"play");
信号的连接
我们可以简单的使用
g_signal_connect(instance, detailed_signal, c_handler, data)
参数对应发射体,信号名,接收体,附加数据(gpointer型)
它直接连接的就是VOID_VOID型的marshal,
当然我们也可以使用更为底层的函式
g_signal_connect_closure_by_id
g_signal_connect_closure
g_signal_connect_data
当然,这些不常用
请发表评论