1.my_demo.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #ifndef _MY_DEMO_H_ #define _MY_DEMO_H_ #include <glib-object.h> #ifdef __cplusplus extern "C" { #endif //宏 #define MY_TYPE_DEMO (my_demo_get_type()) #define MY_DEMO(object) G_TYPE_CHECK_INSTANCE_CAST((object), MY_TYPE_DEMO, MyDemo) #define MY_DEMO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), MY_TYPE_DEMO, MyDemoClass)) #define MY_IS_DEMO(object) G_TYPE_CHECK_INSTANCE_TYPE((object), MY_TYPE_DEMO)) #define MY_IS_DEMO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), MY_TYPE_DEMO)) #define MY_DEMO_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), MY_TYPE_DEMO, MyDemoClass)) typedef struct MyDemoPrivate MyDemoPrivate; struct MyDemoPrivate { gchar *name; gint64 age; }; //实例结构体 typedef struct _MyDemo MyDemo; struct _MyDemo { GObject parent; MyDemoPrivate *priv; }; //类结构体 typedef struct _MyDemoClass MyDemoClass; struct _MyDemoClass { GObjectClass parent_class; }; GType my_demo_get_type(void) G_GNUC_CONST;//my_demo_get_type将会使用宏G_DEFINE_TYPE去实现(G_DEFINE_TYPE(MyDemo,my_demo,G_TYPE_OBJECT)),其中的my通常表示命名空间,demo表示对象名字,get_type为固定字段 MyDemo *my_demo_new(const gchar *name, gint64 age); #ifdef __cplusplus } #endif #endif // _MY_DEMO_H_ |
2.my_demo.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | #include "my_demo.h" #include <stdio.h> enum { PROP_0, PROP_NAME, PROP_AGE, N_PROPERTIES }; #define MY_DEMO_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MY_TYPE_DEMO, MyDemoPrivate)) static void my_demo_init(MyDemo *self); static void my_demo_class_init(MyDemoClass *klass); /* * G_DEFINE_TYPE 可以让 GObject 库的数据类型系统能够识别我们所定义的 MyDemo 类类型, * 它接受三个参数,第一个参数是类名,即 MyDemo;第二个参数则是类的成员函数名称的前缀,例如 my_demo_get_type 函数即为 MyDemo 类的一个成员函数,"my_demo"是它的前缀;第三个参数则指明 MyDemo 类类型的父类型为G_TYPE_OBJECT。 * G_DEFINE_TYPE中会调用一个 g_type_register_static_simple 的函数,这个函数的作用就是将用户自己定义的类型注册到系统中, * G_DEFINE_TYPE还定义了2个函数(my_demo_init 和 my_demo_class_init),需要自己实现这两个函数。它们是对象的初始化函数,相当于c++的构造函数,第一个函数在每个对象创建的时候都会被调用, * 第二个函数只有在第一次创建对象的时候被调用(比如在调用g_type_class_ref的时候,如果class没有初始化,就会调用my_demo_class_init) */ G_DEFINE_TYPE (MyDemo, my_demo, G_TYPE_OBJECT); static void my_demo_dispose(GObject *object); static void my_demo_finalize(GObject *object); /* //以下代码为替换宏G_DEFINE_TYPE的另外一种对my_demo_get_type函数的实现方法,代码不好理解,不建议使用这种方法 static gpointer my_demo_parent_class = ((void*) 0); static void my_demo_class_intern_init(gpointer klass) { my_demo_parent_class = g_type_class_peek_parent(klass); my_demo_class_init ((MyDemoClass*)klass); } GType my_demo_get_type (void) { static volatile gsize g_define_type_id__volatile = 0; if (g_once_init_enter(&g_define_type_id__volatile)) { GType g_define_type_id = g_type_register_static_simple (((GType)((20) << (2))), g_intern_static_string("MyDemo"), sizeof(MyDemoClass), (GClassInitFunc)my_demo_class_intern_init, sizeof(MyDemo), (GInstanceInitFunc)my_demo_init, (GTypeFlags)0); { {{};} } g_once_init_leave(&g_define_type_id__volatile, g_define_type_id); } return g_define_type_id__volatile; } */ static void my_demo_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { MyDemo *self; g_return_if_fail(object != NULL); self = MY_DEMO (object); //self->priv = MY_DEMO_GET_PRIVATE(self); switch (prop_id) { case PROP_NAME: self->priv->name = g_value_dup_string(value); break; case PROP_AGE: self->priv->age = g_value_get_int64(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void my_demo_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { MyDemo *self; g_return_if_fail(object != NULL); self = MY_DEMO(object); switch (prop_id) { case PROP_NAME: g_value_set_string(value, self->priv->name); break; case PROP_AGE: g_value_set_int64(value, self->priv->age); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } //类结构体初始化函数 static void my_demo_class_init(MyDemoClass *klass) { printf("%s\n", __FUNCTION__); int signal_id = g_signal_new("broadcast_msg", my_demo_get_type(),/*G_OBJECT_CLASS_TYPE(kclass)*/ G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE,/*返回值,因为信号没有返回,所以为NONE*/ 1,/*参数数目*/ G_TYPE_STRING/*参数类型*/ ); GObjectClass *object_class = G_OBJECT_CLASS(klass); object_class->finalize = my_demo_finalize; object_class->dispose = my_demo_dispose; object_class->set_property = my_demo_set_property; object_class->get_property = my_demo_get_property; g_object_class_install_property(object_class, PROP_NAME, g_param_spec_string("name", "name", "Specify the name of demo", "Unknown", G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property(object_class, PROP_AGE, g_param_spec_int64 ("age", "age", "Specify age number", G_MININT64, G_MAXINT64, 0, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); // 如果对struct MyDemoPrivate 里面添加了成员变量,则执行下面这行代码 g_type_class_add_private(klass, sizeof(MyDemoPrivate)); } //实例结构体初始化函数 static void my_demo_init(MyDemo *self) { printf("%s\n", __FUNCTION__); self->priv = MY_DEMO_GET_PRIVATE(self); } static void my_demo_dispose(GObject *object) { printf("%s\n", __FUNCTION__); } static void my_demo_finalize(GObject *object) { printf("%s\n", __FUNCTION__); MyDemo *self; g_return_if_fail(object != NULL); self = MY_DEMO(object); if (self->priv->name) g_free (self->priv->name); G_OBJECT_CLASS(my_demo_parent_class)->finalize(object); } MyDemo *my_demo_new(const gchar *name, gint64 age) { MyDemo *demo; demo = MY_DEMO(g_object_new(MY_TYPE_DEMO, "name", name, "age", age, NULL)); printf("get property name:%s, age:%ld\n", demo->priv->name, demo->priv->age); return demo; } |
3.main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | #include <glib.h> #include <glib-unix.h> #include <stdio.h> #include "my_demo.h" static GMainLoop *loop = NULL; static gboolean signal_handler(gpointer user_data) { g_main_loop_quit(loop); return FALSE; } void handler_receive_msg(GObject *sender, char *name, gpointer data) { MyDemo *demo = G_TYPE_CHECK_INSTANCE_CAST(sender, my_demo_get_type(), MyDemo); printf("handler: [%s] from [%s: %ld]\n", name, demo->priv->name, demo->priv->age); } int main(int argc, char* argv[]) { #if !GLIB_CHECK_VERSION(2,32,0) if (! g_thread_supported ()) g_thread_init (NULL); #endif #if !GLIB_CHECK_VERSION(2,36,0) g_type_init (); #endif loop = g_main_loop_new(NULL, FALSE); g_unix_signal_add_full(G_PRIORITY_DEFAULT, SIGINT, signal_handler, NULL, NULL); int i; MyDemo *demos[3]; int len = sizeof(demos) / sizeof(demos[0]); for (i = 0; i < len; i++) { printf("construction demos[%d]\n", i); //创建对象 //demos[i]= g_object_new(MY_TYPE_DEMO, NULL); /*demos[i]= g_object_new(MY_TYPE_DEMO, "name", "kobe", "age", i, NULL);*/ gchar *name = g_strdup_printf("kobe%d", i); demos[i] = my_demo_new(name, i); g_free(name); //绑定信号 g_signal_connect(demos[i], "broadcast_msg", G_CALLBACK(handler_receive_msg), NULL); //发送信号 g_signal_emit_by_name(demos[i], "broadcast_msg", "lixiang"); } //析构 for(i = 0; i < len; i++){ printf("destruction demos[%d]\n", i); g_object_unref(demos[i]); } g_main_loop_run(loop); g_main_loop_unref(loop); return 0; } |
4.Makefile
1 2 3 4 5 6 7 8 9 10 11 12 13 | CC = gcc CC_FLAGS = $(shell pkg-config --cflags glib-2.0 gthread-2.0 gobject-2.0) CC_FLAGS += -std=c99 -g LD_FLAGS = $(shell pkg-config --libs glib-2.0 gthread-2.0 gobject-2.0) gobjectdemo:main.o my_demo.o $(CC) -o $@ $+ $(LD_FLAGS) %.o:%.c $(CC) $(CC_FLAGS) -c -o $@ $< clean: rm -rf *.o gobjectdemo |
5.安装、编译glib
1 2 3 | # sudo apt install libglib2.0-dev # make # ./gobjectdemo |
官网