GObject
- 创建两个结构体
typedef struct _PMDList PMDList;
struct _PMDList {
GObject parent_instance;
PMDListNode *head;
PMDListNode *tail;
};
typedef struct _PMDListClass PMDListClass;
struct _PMDListClass {
GObjectClass parent_class;
};
-
创建三个函数
2.1 ****_get_type 函数 //返回gtype类型,内部注册一次
2.2 类初始化函数 //第一次create object 时被调用
2.3 对象初始化函数 // 每次 create object 时被调用
- 初始化只是赋值,不是malloc
- get_type函数可以通过宏定义自动创建,如
G_DEFINE_TYPE (PMDList, pm_dlist, G_TYPE_OBJECT);
其内部将自动创建。代码如下所示,第一次调用的时候会注册这样一个类型,并且返回一个整数来表示此类型,后期调用直接使用返回类型即可,无需再次注册。
GType viewer_file_get_type (void)
{
static GType type = 0;
if (type == 0) {
const GTypeInfo info = {
sizeof (ViewerFileClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) viewer_file_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (ViewerFile),
0, /* n_preallocs */
(GInstanceInitFunc) NULL /* instance_init */
};
type = g_type_register_static (G_TYPE_OBJECT,
"ViewerFile",
&info, 0);
}
return type;
}
-
使用对象
3.1
g_type_init ();
/* GObject 库的类型管理系统的初始化 */
3.2list = g_object_new (PM_TYPE_DLIST, NULL);
//注意这里面两个函数,第一个参数是函数的返回值,内部会进行一次函数注册,并返回一个GType类型的对象。在glib的世界中,GType是通行证。
3.3g_object_unref (list);
//手动给计数器-1
#ifndef PM_DLIST_H
#define PM_DLIST_H
#include <glib-object.h>
#define PM_TYPE_DLIST (pm_dlist_get_type ())
typedef struct _PMDListNode PMDListNode;
struct _PMDListNode {
PMDListNode *prev;
PMDListNode *next;
void *data;
};
typedef struct _PMDList PMDList;
struct _PMDList {
GObject parent_instance;
PMDListNode *head;
PMDListNode *tail;
};
typedef struct _PMDListClass PMDListClass;
struct _PMDListClass {
GObjectClass parent_class;
};
GType pm_dlist_get_type (void);
#endif
#include "pm-dlist.h"
G_DEFINE_TYPE (PMDList, pm_dlist, G_TYPE_OBJECT);
static
void pm_dlist_init (PMDList *self)
{
g_printf ("\tobject init\n");
self->head = NULL;
self->tail = NULL;
}
static
void pm_dlist_class_init (PMDListClass *klass)
{
g_printf ("class init\n");
}
#include "pm-dlist.h"
int main (void)
{
/* GObject 库的类型管理系统的初始化 */
g_type_init ();
int i;
PMDList *list;
/* 进行三次对象实例化 */
for (i = 0; i < 3; i++){
list = g_object_new (PM_TYPE_DLIST, NULL);
g_object_unref (list);
}
/* 检查实例是否为 GObject 对象 */
list = g_object_new (PM_TYPE_DLIST, NULL);
if (G_IS_OBJECT (list))
g_printf ("\t这个实例是一个 GObject 对象!\n");
return 0;
}
glib
source/event
The creation of a new source requires us to define at least 3 functions:
-
prepare(): Called before all the file descriptors are polled. If the source can determine that it is ready here (without waiting for the results of the poll() call), it should return TRUE. It can also return a time-out value which should be the maximum time-out (in milliseconds) which should be passed to the poll() call. The actual time-out used will be -1 if all sources returned -1, or it will be the minimum of all the timeout_values returned which were >= 0
-
check(): Called after all the file descriptors are polled. The source should return TRUE if it is ready to be dispatched.
Time may have passed since the previous prepare function was called, so the source should be checked again.
-
dispatch() Called to dispatch the event source after it has returned TRUE in either its prepare or check function. The dispatch function is passed in a callback function and data. The callback function may be NULL if the source was never connected to a callback using g_source_set_callback(). The dispatch function should call the callback function with user_data and the additional parameters that are needed for this type of event source.
- prepare 中的timeout测试发现是 prepare到check的时间,check完之后会立即进入prepare
- check与prepare只要一个返回TRUE,dispatch 函数就执行
#include <glib.h>
gboolean callback(gpointer data)
{
static int i = 0;
i++;
g_print ("timeout_callback called %d times\n",i);
if (10 == i)
{
g_main_loop_quit((GMainLoop*)data);
return FALSE;
}
return TRUE;
}
gboolean prepare(GSource *source,gint *timeout_)
{
*timeout_ = -1;
return TRUE;
}
gboolean check(GSource *source)
{
return TRUE;
}
gboolean dispatch(GSource *source,GSourceFunc callback,gpointer user_data)
{
if (callback(user_data))
return TRUE;
else
return FALSE;
}
int main()
{
GMainLoop *loop = NULL;
GMainContext *context;
GSource *source;
int id;
//create a variable of type GSourceFuncs
GSourceFuncs SourceFuncs =
{
prepare,
check,
dispatch,
NULL
};
//create a new source
source = g_source_new (&SourceFuncs, sizeof(GSource));
//create a context
context = g_main_context_new ();
//attach source to context
id = g_source_attach (source,context);
//create a main loop with context
loop = g_main_loop_new (context,FALSE);
//set the callback for this source
g_source_set_callback (source,callback,loop,NULL);
g_main_loop_run (loop);
g_main_loop_unref (loop);
return 0;
}
https://blog.youkuaiyun.com/u010009623/article/details/53101492
thread & mutex
static GMutex *mutex = NULL;
static gboolean t1_end = FALSE;
static gboolean t2_end = FALSE;
typedef struct _Arg Arg;
struct _Arg
{
GMainLoop* loop;
gint max;
};
void run_1(Arg *arg)
{
int i ;
for(i=0; i<arg->max;)
{
if(g_mutex_trylock(mutex))
{
g_print("%d : thread 1 locked mutex \n", i);
g_usleep(1000000);
i++;
g_mutex_unlock(mutex);
}
}
t1_end = TRUE;
}
void run_2(Arg *arg)
{
int i;
for(i=0; i<arg->max;)
{
if(g_mutex_trylock(mutex))
{
g_print("%d : thread 2 locked mutex \n", i);
g_usleep(10);
i++;
g_mutex_unlock(mutex);
}
}
t2_end = TRUE;
}
void run_3(Arg *arg)
{
for(;;)
{
if(t1_end && t2_end)
{
g_main_loop_quit(arg->loop);
break;
}
}
}
int main(int argc, char *argv[])
{
GMainLoop *mloop;
Arg *arg;
if(!g_thread_supported())
g_thread_init(NULL);
mloop = g_main_loop_new(NULL, FALSE);
arg = g_new(Arg, 1);
arg->loop = mloop;
arg->max = 11;
mutex = g_mutex_new();
g_thread_create(run_1, arg, TRUE, NULL);
g_thread_create(run_2, arg, TRUE, NULL);
g_thread_create(run_3, arg, TRUE, NULL);
g_main_loop_run(mloop);
g_print("thread 3 exit \n");
g_mutex_free(mutex);
g_print("free mutex \n");
g_free(arg);
g_print("free all memory\n");
}
signal
https://developer.gnome.org/gobject/stable/howto-signals.html
- 新建一个signal object //在class init中
- 关联到某个callback
- emit signal
static
void pm_dlist_class_init (PMDListClass *klass)
{
g_printf ("class init\n");
mysignal = g_signal_newv ("changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
NULL /* closure */,
NULL /* accumulator */,
NULL /* accumulator data */,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE /* return_type */,
0 /* n_params */,
NULL /* param_types */);
}
void changed_event()
{
g_print("triger signal \n");
}
int main (void)
{
/* GObject 库的类型管理系统的初始化 */
g_type_init ();
int i;
PMDList *list;
list = g_object_new (PM_TYPE_DLIST, NULL);
g_signal_connect (list, "changed", G_CALLBACK (changed_event), NULL);
g_signal_emit (list, mysignal, 0 /* details */);
return 0;
}
GType viewer_file_get_type (void)
{
static GType type = 0;
if (type == 0) {
const GTypeInfo info = {
sizeof (ViewerFileClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) viewer_file_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (ViewerFile),
0, /* n_preallocs */
(GInstanceInitFunc) NULL /* instance_init */
};
type = g_type_register_static (G_TYPE_OBJECT,
"ViewerFile",
&info, 0);
}
return type;
}