GLib 实现了一个功能强大的事件循环分发处理机制,GLib 内部实现了三种类型的事件源,分别是 Timeout, Idle, Child Watch。同时也支持创建自定义的事件源。
本文主要讲解自定义事件源的基本作用和如何创建自定义事件源。
自定义事件源的基本作用
自定义的事件源可以用来检查、分发处理 GLib 没有封装的用户自定义的事件。
如何创建自定义事件源
GLib 提供了一系列的接口用于创建自定义的事件源,下面我们先讲解一下创建事件源的基本函数和数据结构,最后给出一个实例。
这个函数用于创建一个自定义事件源,新的事件源可以使用 g_source_attach() 函数加入到主循环上下文中。
GSource * g_source_new(GSourceFuncs * source_funcs, guint struct_size);
source_funcs : 包含用于实现事件行为的函数的结构
struct_size : 创建的 GSource 结构大小,不能小于 sizeof(GSource)
返回值 : 返回新创建的 GSource
typedef struct { gboolean (*prepare) (GSource * source, gint * timeout); gboolean (*check) (GSource * source); gboolean (*dispatch) (GSource * source, GSourceFunc callback, gpointer data); void (*finalize) (GSource * source); /* For use by g_source_set_cosure */ GSourceFunc closure_callback; GSourceDummyMarshal closure_marshal; } GSourceFuncs;
这是包含用于实现事件行为的函数的结构体。
prepare : 设置检查事件时间超时。如果返回 TRUE, check 会立刻被调用;如果返回 FALSE 并设置了 timeout , timeout 时间后 check 会被调用。
check : 检查事件是否准备完毕。返回 TRUE 为准备完毕, dispatch 会被立刻调用;返回 FALSE 不调用 dispatch,进入下一次事件循环。
dispatch : 分发事件。返回 TRUE 将继续下一次操作循环;返回 FALSE 中止本事件源的事件循环。
finalize : 当事件源被移除时被调用。
guint g_source_attach(GSource * source, GMainContext * context);
增加事件源到一个主循环上下文中。
source : 事件源对象
context : 主循环上下文对象
返回值 : 主循环上下文中的事件源ID(大于 0)
实例
#include <glib.h> gboolean source_prepare_cb(GSource * source, gint * timeout) { g_printf("prepare\n"); *timeout = 1000; return FALSE; } gboolean source_check_cb(GSource * source) { g_printf("check\n"); return TRUE; } gboolean source_dispatch_cb(GSource * source, GSourceFunc callback, gpointer data) { g_printf("dispatch\n"); return TRUE; } void source_finalize_cb(GSource * source) { g_printf("finalize\n"); } int main(int argc, char * argv[]) { GMainLoop * mainloop; GMainContext * maincontext; GSource * source; GSourceFuncs sourcefuncs; sourcefuncs.prepare = source_prepare_cb; sourcefuncs.check = source_check_cb; sourcefuncs.dispatch = source_dispatch_cb; sourcefuncs.finalize = source_finalize_cb; mainloop = g_main_loop_new(NULL, FALSE); maincontext = g_main_loop_get_context(mainloop); source = g_source_new(&sourcefuncs, sizeof(GSource)); g_source_attach(source, maincontext); g_main_loop_run(mainloop); return 0; }