gobject get and set property

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010643777/article/details/88924613

 关于gobject中的私有成员变量的setter和getter,[1]已经有很详细的介绍了。我在这里,把自己联系的例子贴上来。
 gobject自定义对象中的头文件一般都有类似下面的宏定义:

#define MY_PARENT_TYPE (my_parent_get_type ())
#define MY_PARENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_PARENT_TYPE, MyParent))
#define MY_IS_PARENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_PARENT_TYPE))
#define MY_PARENT_CLASS(klass) \
        (G_TYPE_CHECK_CLASS_CAST ((klass), MY_PARENT_TYPE, MyParentClass))
#define MY_IS_PARENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MY_PARENT_TYPE))
#define MY_PARENT_GET_CLASS(obj) \
        (G_TYPE_INSTANCE_GET_CLASS ((obj),MY_PARENT_TYPE,MyParentClass))
        
typedef struct _MyParent MyParent;
typedef struct _MyParentClass MyParentClass;        

每次都去改这些字符串,重复性的劳动,令人生厌。于是我用python写了个小工具,可以自动生成这样的头文件,下载[3]。用法"python g-object-template.py my parent",在这里,my可以认为是对c++中namespace的模仿,生成的对象就是MyParent。
 其中MY_IS_PARENT(obj)是用来判断传入的参数是否是MyParent类型。比如会在下面的函数中用到:

void my_parent_free(MyParent *self){
    g_assert(self!= NULL);
    g_return_if_fail(lazy_is_obj(MY,PARENT,self));
    g_object_unref(G_OBJECT(self));
}

 这段代码我也不想写,也在g-object-template.py中生成,复制粘贴就行了。lazy_micro.h中的内容是:

#define lazy_is_obj(ns,type,obj) (ns##_IS_##type(obj))
#define lazy_is_class(ns,type,kclass) (ns##_IS_##type##_CLASS(kclass))

就是把lazy_is_obj(MY,PARENT,self)转成MY_IS_PARENT(self)。
 下面开始贴代码:
my_parent.h

#include <glib-object.h>
#define MY_PARENT_TYPE (my_parent_get_type ())
#define MY_PARENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_PARENT_TYPE, MyParent))
#define MY_IS_PARENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_PARENT_TYPE))
#define MY_PARENT_CLASS(klass) \
        (G_TYPE_CHECK_CLASS_CAST ((klass), MY_PARENT_TYPE, MyParentClass))
#define MY_IS_PARENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MY_PARENT_TYPE))
#define MY_PARENT_GET_CLASS(obj) \
        (G_TYPE_INSTANCE_GET_CLASS ((obj),MY_PARENT_TYPE,MyParentClass))

typedef struct _MyParent MyParent;
typedef struct _MyParentClass MyParentClass;
typedef struct _MyParentPriv MyParentPriv;
struct _MyParentPriv{
    gint a;   
};
struct _MyParent{
    GObject parent;
};
struct _MyParentClass{
    GObjectClass parent_class;
};
GType my_parent_get_type (void);
MyParent *my_parent_new(void);
void my_parent_free(MyParent *self);

my_parent.c

#include "lazy_micro.h"
#include "my_parent.h"
G_DEFINE_TYPE (MyParent, my_parent, G_TYPE_OBJECT);
#define MY_PARENT_GET_PRIVATE(obj) \
        G_TYPE_INSTANCE_GET_PRIVATE ((obj),MY_PARENT_TYPE,MyParentPriv)
enum{
PROP_0,//must
PROP_A,
};
void my_parent_dispose(GObject *gobject){
    G_OBJECT_CLASS (my_parent_parent_class)->dispose(gobject);
}
void my_parent_finalize(GObject *gobject){
    G_OBJECT_CLASS (my_parent_parent_class)->finalize(gobject);
}
void my_parent_set_prop(GObject      *object,
                   guint         prop_id,
                   const GValue *value,
                   GParamSpec   *pspec){
	MyParent *self=MY_PARENT(object);
    MyParentPriv *priv=MY_PARENT_GET_PRIVATE(self);
	switch(prop_id){
	case PROP_A:{
		priv->a=g_value_get_int(value);
		break;
	}
	default:{
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
	}
	}
}
void my_parent_get_prop(GObject    *object,
                   guint       prop_id,
                   GValue     *value,
                   GParamSpec *pspec){
	MyParent *self=MY_PARENT(object);
    MyParentPriv *priv=MY_PARENT_GET_PRIVATE(self);
	switch(prop_id){
	case PROP_A:{
		g_value_set_int(value,priv->a);
		break;
	}
	default:{
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
	}
	}
}
static void my_parent_init(MyParent *self){

}
static void my_parent_class_init(MyParentClass *kclass){
    g_type_class_add_private (kclass, sizeof (MyParentPriv));
    GObjectClass *base_class = G_OBJECT_CLASS (kclass);
    base_class->dispose      = my_parent_dispose;
    base_class->finalize      = my_parent_finalize;
    base_class->set_property=my_parent_set_prop;
    base_class->get_property=my_parent_get_prop;
    
    g_object_class_install_property (base_class, PROP_A,
                                     g_param_spec_int ("a",
                                                        "A",
                                                        "The A",
                                                        -1,
                                                        G_MAXINT,
                                                        -1,
                                                        G_PARAM_READWRITE));

}
MyParent *my_parent_new(void){
    MyParent *ins;
    ins = g_object_new(MY_PARENT_TYPE, 0);
    return ins;
}
void my_parent_free(MyParent *self){
    g_assert(self!= NULL);
    g_return_if_fail(lazy_is_obj(MY,PARENT,self));
    g_object_unref(G_OBJECT(self));
}

 需要注意的是,设置属性的PROP_ID一定要大于0,所以定义了PROP_0。 g_type_class_add_private (kclass, sizeof (MyParentPriv));这句话就是在结构体MyParent被初始化初始化,可以为私有成员分配存储空间。也比较符合c++中对私有变量的定义,在外部是不同从结构体MyParent获取相应的值。
 我写这个例子,也是为了证明,在父类为子类继承的情况下,能够通过property_name获取和设置父类中的私有成员。结果是可以的。
my_child.h

#include <glib-object.h>
#include "my_parent.h"
#define MY_CHILD_TYPE (my_child_get_type ())
#define MY_CHILD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_CHILD_TYPE, MyChild))
#define MY_IS_CHILD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_CHILD_TYPE))
#define MY_CHILD_CLASS(klass) \
        (G_TYPE_CHECK_CLASS_CAST ((klass), MY_CHILD_TYPE, MyChildClass))
#define MY_IS_CHILD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MY_CHILD_TYPE))
#define MY_CHILD_GET_CLASS(obj) \
        (G_TYPE_INSTANCE_GET_CLASS ((obj),MY_CHILD_TYPE,MyChildClass))

typedef struct _MyChild MyChild;
typedef struct _MyChildClass MyChildClass;
typedef struct _MyChildPriv MyChildPriv;
struct _MyChildPriv{
    gint b;
};
struct _MyChild{
    MyParent parent;
    MyChildPriv priv;
};
struct _MyChildClass{
    MyParentClass parent_class;
};


GType my_child_get_type (void);
MyChild *my_child_new(int a,int b);
void my_child_free(MyChild *self);

my_child.c

#include "lazy_micro.h"
#include "my_child.h"
G_DEFINE_TYPE (MyChild, my_child, MY_PARENT_TYPE);
enum{
PROP_0,//must
PROP_B,
};
void my_child_dispose(GObject *gobject){
    G_OBJECT_CLASS (my_child_parent_class)->dispose(gobject);
}
void my_child_finalize(GObject *gobject){
    G_OBJECT_CLASS (my_child_parent_class)->finalize(gobject);
}
static void my_child_init(MyChild *self){

}
void my_child_set_prop(GObject      *object,
                   guint         prop_id,
                   const GValue *value,
                   GParamSpec   *pspec){
	MyChild *self=MY_CHILD(object);
	switch(prop_id){
	case PROP_B:{
		self->priv.b=g_value_get_int(value);
		break;
	}

	default:{
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
	}
	}
}
void my_child_get_prop(GObject    *object,
                   guint       prop_id,
                   GValue     *value,
                   GParamSpec *pspec){
	MyChild *self=MY_CHILD(object);
	switch(prop_id){
	case PROP_B:{
		g_value_set_int(value,self->priv.b);
		break;
	}
	default:{
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
	}
	}
}
static void my_child_class_init(MyChildClass *kclass){
    GObjectClass *base_class = G_OBJECT_CLASS (kclass);
    base_class->dispose      = my_child_dispose;
    base_class->finalize      = my_child_finalize;
    base_class->set_property=my_child_set_prop;
    base_class->get_property=my_child_get_prop;

    g_object_class_install_property (base_class, PROP_B,
                                     g_param_spec_int ("b",
                                                        "B",
                                                        "The B",
                                                        -1,
                                                        G_MAXINT,
                                                        -1,
                                                        G_PARAM_READWRITE));
}
MyChild *my_child_new(int a,int b){
    MyChild *ins;
    ins = g_object_new(MY_CHILD_TYPE,"a",a,"b",b, 0);
    return ins;
}
void my_child_free(MyChild *self){
    g_assert(self!= NULL);
    g_return_if_fail(lazy_is_obj(MY,CHILD,self));
    g_object_unref(G_OBJECT(self));
}

主文件,child-test.c

#include "my_child.h"
#include <glib.h>
//http://garfileo.is-programmer.com/
//https://blog.csdn.net/knowledgebao/article/details/82427406
int main(){
    MyChild *child=my_child_new(1,2);
    //GValue value = {0};
    //g_value_init(&value,G_TYPE_INT);
    //g_value_set_int(&value, 400);
    //g_object_set_property(G_OBJECT(child), "b", &value);
    //g_value_unset (&value);
    
    GValue val = {0};
    g_value_init(&val,G_TYPE_INT);    
    g_object_get_property(G_OBJECT(child),"a",&val);
    int b=g_value_get_int(&val);
    g_value_unset (&val);    
    my_child_free(child);
    g_print("a %d\n",b);
}

 怎么编译,我使用的是cmake文件,完整工程[4]。
[1] GObject学习教程—第四章:GObject 子类私有属性的外部访问 https://blog.csdn.net/knowledgebao/article/details/82427406
[2] GObject的对象属性 https://blog.csdn.net/absurd/article/details/631595
[3] GOBJECT header generator https://github.com/SoonyangZhang/gobject-example/tree/master/gobjet-tools
[4]gobject-example https://github.com/SoonyangZhang/gobject-example

猜你喜欢

转载自blog.csdn.net/u010643777/article/details/88924613