我有一些结构要初始化,手动操作会很繁琐。我想创建一个可以帮助我的宏...但我不确定 C 预处理器是否足够好。
我有结构代表菜单。它们仅由函数指针组成:
typedef uint8_t (*button_handler) (uint8_t);
typedef void (*pedal_handler) (void);
typedef void (*display_handler) (void);
typedef void (*menu_switch_handler) (void);
#define ON_BUTTON(x) uint8_t menu_frame_##x##_button (uint8_t button)
#define ON_PEDAL(x) void menu_frame_##x##_pedal (void)
#define ON_DISPLAY(x) void menu_frame_##x##_display (void)
#define ON_SWITCH(x) void menu_frame_##x##_switch (void)
typedef struct menu_frame {
button_handler on_button;
pedal_handler on_pedal;
display_handler on_display;
menu_switch_handler on_switch;
} menu_frame;
这允许我将函数和单独的函数编写为(.c文件):
ON_BUTTON(blah) { ... }
和菜单为(.h文件):
ON_BUTTON(blah);
ON_DISPLAY(blah);
menu_frame menu_frame_blah = {
menu_frame_blah_button,
NULL,
menu_frame_blah_display,
NULL
};
有什么办法可以将菜单定义折叠成一个定义吗?当然,我可以做一些扩展MENU(blah, menu_frame_blah_button, NULL, menu_frame_blah_display, NULL)
的事情,但有没有办法:
ON_BUTTON(...);
的需要
理想情况下,我希望MENU(blah, button, NULL, display, NULL)
同时定义处理程序和菜单结构本身。我不知道如何防止将上一个词扩展为ON_SWITCH(NULL)
。
或许我应该从其他方面接近它?
答案 0 :(得分:1)
我之前编写过Python脚本来为我生成这种代码。您可能希望沿着该路线前进,然后将脚本运行到构建过程中。
答案 1 :(得分:0)
您无法在C中进行条件宏扩展,因此您的宏将根据参数进行不同的扩展,如:在宏定义中不能使用#if。
我想你能得到的最好的东西就像MENU(blah, ITEM(blah,button), NULL, ITEM(blah,display), NULL)
,你还需要一个单独的原型集,因为缺乏条件扩展。
就个人而言,我会编写一个简单的脚本来生成那种样板代码。一个能理解你所需语法的人。在Python或任何最适合你的地方......
答案 2 :(得分:0)
您可以单独在预处理器中编写条件,有限循环,默认参数和所有此类内容。 Boost库在其预处理器部分中有一些实现。 Boost主要用于C ++,但预处理器的东西基本上也应该用在C语言中。
通过这些技术,您可以编写复杂的宏,但使用起来很简单。使用C99而不是C89(你已命名初始值设定项和 VA_ARGS )时,实现起来会更简单,但仍然可以。