使用C语言进行面向对象的开发--GObject入门[10]

转载请注明出处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_newg_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
当然,这些不常用

 

 

 

 

 

 

 

posted @ 2010-01-23 22:45  平繁  阅读(2791)  评论(0编辑  收藏  举报