在嵌入式开发领域,当需要高效利用有限资源或应对大量异步操作时,采用事件驱动架构能显著提升系统的性能和可靠性。
本次推荐一个轻量级事件管理库——lwevt。
lwevt 简介
基本介绍
https://github.com/MaJerle/lwevt
lwevt 是一款专为嵌入式系统打造的轻量级事件管理库,基于 C 语言开发。它的设计目标是提供高效、简洁的事件处理机制,帮助开发者快速实现事件驱动的应用程序。
该库具有良好的跨平台性,能够在多种嵌入式操作系统和硬件平台上稳定运行,为嵌入式设备的事件管理提供了可靠的解决方案。
特性
- 独立于平台,没有特定的架构代码
- 灵活的应用程序定义的事件类型和相关数据
- 易于使用和维护
- 用户友好的MIT许可
lwevt 使用
下载源码:
git clone --recurse-submodules https://github.com/MaJerle/lwevt
下面演示lvevt的使用:
#include <stdio.h>
#include <string.h>
#include "lwevt/lwevt.h"
static void prv_evt_fn_1(lwevt_t* e) {
switch ((unsigned)e->type){
case LWEVT_TYPE_MY_EXT_1: {
printf("Event fn 1, LWEVT_TYPE_MY_EXT_1 - with data: a: %d, b: %d\r\n",
(int)e->msg.a.a, (int)e->msg.a.b);
break;
}
default:
break;
}
}
static void prv_evt_fn_2(lwevt_t* e) {
switch ((unsigned)e->type){
case LWEVT_TYPE_MY_EXT_2: {
printf("Event fn 2, LWEVT_TYPE_MY_EXT_2 - with data: a: %d, b: %d\r\n",
(int)e->msg.b.a, (int)e->msg.b.a);
break;
}
default:
break;
}
}
int main(void) {
lwevt_t* evt;
lwevt_t evt_local;
// 初始化事件系统
lwevt_init();
// 注册两个用户事件监听器
lwevt_register(prv_evt_fn_1);
lwevt_register(prv_evt_fn_2);
evt = lwevt_get_handle(); // 获取默认事件句柄
evt->msg.a.a = 1;
evt->msg.a.b = 2;
lwevt_dispatch(LWEVT_TYPE_MY_EXT_1); // 分发事件,所有监听器都会收到
evt_local.msg.b.a = 3;
evt_local.msg.b.b = 4;
lwevt_dispatch_ex(&evt_local, LWEVT_TYPE_MY_EXT_2); // 用本地句柄分发事件
return 0;
}
为了优化内存消耗,在LwEVT中将主事件句柄定义为静态全局变量。它可以通过lwevt_get_handle()函数访问,并允许使用默认的lwevt_dispatch()函数分发事件。
lwevt_get_handle()和lwevt_dispatch()只有当
LWEVT_CFG_ENABLE_DEFAULT_HANDLE(
lwevt/src/include/lwevt/lwevt_opt.h)被启用时才可用。
在多线程环境中,应用程序必须保证get句柄和dispatch调用之间的线程安全。
为了避免使用信号量或互斥锁,可以定义基于lwevt_t的本地变量,并使用lwevt_dispatch_ex()函数分发事件。
在LwEVT中,事件类型和事件数据的定义采用了X-Macro技术。
在 C 语言中,X-Macro 技术是一种利用预处理宏(Preprocessor Macro)实现代码复用与一致性维护的编程技巧。它的核心思想是:将一组相关的数据或结构以 “宏列表” 的形式定义,然后通过重新定义宏的展开方式,在不同场景下对这组数据进行不同形式的处理,从而避免重复编写相似代码,同时保证数据与相关操作的一致性。
使得事件类型和事件数据可以通过单独的lwevt_types.h文件来维护,如lwevt_types.h的内容可以根据需要自定义定义事件类型及事件数据:
LWEVT_TYPE_BASIC(LWEVT_TYPE_MY_BASIC_1)
LWEVT_TYPE_BASIC(LWEVT_TYPE_MY_BASIC_2)
LWEVT_TYPE_BASIC(LWEVT_TYPE_MY_BASIC_3)
LWEVT_TYPE_EXT(
LWEVT_TYPE_MY_EXT_1, struct {
int a;
int b;
} a)
LWEVT_TYPE_EXT(
LWEVT_TYPE_MY_EXT_2, struct {
int a;
int b;
} b)
LWEVT_TYPE_EXT(
LWEVT_TYPE_MY_EXT_3, struct {
int a;
int b;
} c)
/* Add more types here ... */
lwevt.h采用了X-Macro技术定义LwEVT的核心接口和数据结构,主要内容如下:
事件类型定义
typedef enum {
#define LWEVT_TYPE_BASIC(name) name,
#define LWEVT_TYPE_EXT(name, data) name,
#include "lwevt/lwevt_type.h"
LWEVT_TYPE_LAST
} lwevt_type_t;
lwevt_type.h:
#ifndef LWEVT_TYPE_BASIC
#define LWEVT_TYPE_BASIC(name)
#endif
#ifndef LWEVT_TYPE_EXT
#define LWEVT_TYPE_EXT(name, data)
#endif
/* Include user types */
#include "lwevt_types.h"
/* Undefine type back - after use */
#undef LWEVT_TYPE_BASIC
#undef LWEVT_TYPE_EXT
事件类型通过宏展开和 lwevt_type.h 文件定义,支持扩展。
事件结构体
typedef struct {
lwevt_type_t type; // 事件类型
union {
#define LWEVT_TYPE_EXT(name, data) data;
#include "lwevt/lwevt_type.h"
const unsigned int dummy;
} msg; // 事件消息体,支持扩展数据
} lwevt_t;
- type 字段标识事件类型。
- msg 联合体用于存储扩展事件的数据(通过宏和 lwevt_type.h 支持多种事件数据结构)。