【C语言】宏定义中X-Micro的使用
C语言宏定义中X-Micro的使用
在LVGL源码中,全局变量初始化,以及函数声明和定义(LV_ROOTS)的时候的时候,使用到了X-Micro,下面拆解一下这个宏的用法。
下列代码来自:lv_gc.h 头文件
#define LV_DISPATCH(f, t, n) f(t, n)
#define LV_ITERATE_ROOTS(f) \
LV_DISPATCH(f, lv_ll_t, _lv_timer_ll) /*Linked list to store the lv_timers*/ \
LV_DISPATCH(f, lv_ll_t, _lv_disp_ll) /*Linked list of display device*/ \
LV_DISPATCH(f, lv_ll_t, _lv_indev_ll) /*Linked list of input device*/ \
LV_DISPATCH(f, lv_ll_t, _lv_fsdrv_ll) \
LV_DISPATCH(f, lv_ll_t, _lv_anim_ll) \
LV_DISPATCH(f, lv_ll_t, _lv_group_ll) \
LV_DISPATCH(f, lv_ll_t, _lv_img_decoder_ll) \
LV_DISPATCH(f, lv_ll_t, _lv_obj_style_trans_ll) \
LV_DISPATCH(f, lv_layout_dsc_t *, _lv_layout_list) \
LV_DISPATCH_COND(f, _lv_img_cache_entry_t*, _lv_img_cache_array, LV_IMG_CACHE_DEF, 1) \
LV_DISPATCH_COND(f, _lv_img_cache_entry_t, _lv_img_cache_single, LV_IMG_CACHE_DEF, 0) \
LV_DISPATCH(f, lv_timer_t*, _lv_timer_act) \
LV_DISPATCH(f, lv_mem_buf_arr_t , lv_mem_buf) \
LV_DISPATCH_COND(f, _lv_draw_mask_radius_circle_dsc_arr_t , _lv_circle_cache, LV_DRAW_COMPLEX, 1) \
LV_DISPATCH_COND(f, _lv_draw_mask_saved_arr_t , _lv_draw_mask_list, LV_DRAW_COMPLEX, 1) \
LV_DISPATCH(f, void * , _lv_theme_default_styles) \
LV_DISPATCH(f, void * , _lv_theme_basic_styles) \
LV_DISPATCH_COND(f, uint8_t *, _lv_font_decompr_buf, LV_USE_FONT_COMPRESSED, 1) \
LV_DISPATCH(f, uint8_t * , _lv_grad_cache_mem)
#define LV_DEFINE_ROOT(root_type, root_name) root_type root_name;
#define LV_ROOTS LV_ITERATE_ROOTS(LV_DEFINE_ROOT)
#define LV_GC_ROOT(x) x
#define LV_EXTERN_ROOT(root_type, root_name) extern root_type root_name;
LV_ITERATE_ROOTS(LV_EXTERN_ROOT)
在LVGL中,调用 LV_ROOTS 宏声明全局变量,下面拆解宏,宏的拆解从内到外,由于前面
#define LV_DISPATCH(f, t, n) f(t, n)
#define LV_ITERATE_ROOTS(f) \
f(lv_ll_t, _lv_timer_ll) /*Linked list to store the lv_timers*/ \
f(lv_ll_t, _lv_disp_ll) /*Linked list of display device*/ \
f(lv_ll_t, _lv_indev_ll) /*Linked list of input device*/
...... // 其余省略
根据这条宏定义:
LV_DEFINE_ROOT(root_type, root_name) root_type root_name;
把 f 替换为 LV_DEFINE_ROOT,因此就变为:
#define LV_ITERATE_ROOTS(LV_DEFINE_ROOT) \
LV_DEFINE_ROOT(lv_ll_t, _lv_timer_ll) /*Linked list to store the lv_timers*/ \
LV_DEFINE_ROOT(lv_ll_t, _lv_disp_ll) /*Linked list of display device*/ \
LV_DEFINE_ROOT(lv_ll_t, _lv_indev_ll) /*Linked list of input device*/
...... // 其余省略
而
LV_DEFINE_ROOT(lv_ll_t, _lv_timer_ll)
展开之后便是:
lv_ll_t _lv_timer_ll;
其他的同理,因此这里就对全局链表进行了声明;
如果要把全局变量属性设置为extern,给外部文件使用,只需要修改一下宏,改为下面这种形式,只需要修改一下 宏定义,就可以完成所有全局变量的声明:
#define LV_EXTERN_ROOT(root_type, root_name) extern root_type root_name;
LV_ITERATE_ROOTS(LV_EXTERN_ROOT)
总结:
使用 X-Macro 宏集中管理全局变量,减少代码更简洁,同时提升代码可维护性;