GLib 实现了一个功能强大的事件循环分发处理机制,被抽象成为 GMainLoop,用于循环处理事件源上的事件。每个 GMainLoop 都工作在指定的 GMainContext 上。事件源在 GLib 中则被抽象成了 GSource。在 GMainContext 中有一个 GSource 列表。GLib 内部定义实现了三种类型的事件源,分别是 Idle, Timeout 和 I/O。同时也支持创建自定义的事件源。(四种事件源:自定义事件源,Idle,Timeout,I/O)
自定义事件源的基本作用
自定义的事件源可以用来将外部信号(事件)挂到程序中的指定主循环上,从而在 g_main_loop_run 中可以响应这些事件。(例如:可以当个定时器使用)
如何创建自定义事件源
GLib 提供了一系列的接口用于创建自定义的事件源,下面我们先讲解一下创建事件源的基本函数和数据结构,最后给出一些实例。
自定义的事件源是一个继承 GSource 的结构体,即自定义事件源的结构体 的第一个成员是 GSource 结构体, 其后便可放置程序所需数据, 例如:
typedef struct _MySource MySource;
struct _MySource
{
GSource _source;
gchar text[256];
}
实现了事件源数据结构的定义之后,还需要
实现事件源所规定的接口,主要为 prepare, check, dispatch, finalize
等事件处理函数(回调函数),它们包含于 GSourceFuncs 结构体中。将 GSourceFuncs 结构以及事件源结构的存储空间宽度作为参数传给 g_source_new 便可构造一个新的事件源,继而可使用 g_source_attach 函数将新的事件源添加到主循环上下文中。下面这个示例可创建一个只会讲“Hello world!”的事件源,并将其添加到主事件循环默认的 GMainContext 中。
#include <glib.h>
#include <glib/gprintf.h>
typedef struct _MySource MySource;
struct _MySource
{
GSource source;
gchar text[256];
};
static gboolean prepare(GSource *source, gint *timeout)
{
*timeout = 0;
return TRUE;
}
static gboolean check(GSource *source)
{
return TRUE;
}
static gboolean dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
{
MySource *mysource = (MySource *)source;
g_print("%s\n", mysource->text);
return TRUE;
}
int main(void)
{
GMainLoop *loop = g_main_loop_new(NULL, TRUE);
GMainContext *context = g_main_loop_get_context(loop);
GSourceFuncs source_funcs = {
prepare, check, dispatch, NULL};
GSource *source = g_source_new(&source_funcs, sizeof(MySource));
g_sprintf(((MySource *)source) |