我要建议你的是我在一个真正的大型制作项目中实际看到的东西。我不得不说,因为我承认这不是一个好看的解决方案。
一个包含所有调用宏的文件
首先,您需要将所有宏调用放在一个文件中。你可以给它命名和你想要的扩展名:例如经典的.h扩展名或带有描述性扩展名的东西,如.def。
所以,PreprocessorTypePopulation.h可以定义如下:
FOO_CREATE(my_name, my_validate, 0, 0)
FOO_CREATE(my_name2, NULL, 0, 0)
它包含所有调用的FOO_CREATE 宏。
注意:每次宏调用后不能有逗号或分号。在这种情况下,也可以使用逗号实现(从宏中删除它们)(因为只涉及枚举项和数组元素)。
包含生成的结构/枚举的文件:
这可以是.h 文件。在我的示例中,它是包含虚拟演示 main() 的 C 文件。我刚刚将 OP 的 int 类型转换为 stdint.h 中包含的类型。
#include <stddef.h>
#include <stdint.h>
#ifdef FOO_CREATE
#undef FOO_CREATE
#endif
/* Enum creation macro */
#define FOO_CREATE(nm,func,val,chgd) nm##_FOO,
typedef enum {
#include "PreprocessorTypePopulation.h"
FOO_COUNT
} foo_id;
struct foo {
char *name;
int (*validate)(uint8_t *data, size_t size);
uint8_t value;
uint8_t changed;
foo_id id;
};
typedef struct foo foo_t;
int my_validate(uint8_t *data, size_t size)
{
return 0;
}
#undef FOO_CREATE
/* Array creation macro */
#define FOO_CREATE(nm,func,val,chgd) \
{ \
.name = (char *) #nm, \
.validate = func, \
.value = val, \
.changed = chgd, \
.id = nm##_FOO \
},
static foo_t foo[FOO_COUNT] = {
#include "PreprocessorTypePopulation.h"
};
int main(void)
{
return 0;
}
如您所见,实现了以下策略:
-
Undef 任何以前的
FOO_CREATE() 定义
- 为第一个任务(枚举生成)定义
FOO_CREATE() 宏
- 在枚举中包含
.def 文件INSIDE。 FOO_CREATE()s的序列将用于根据刚刚定义的宏生成枚举项
- 再次取消定义宏,并为第二个任务(结构数组定义)重新定义它
- 在数组定义中包含
.def 文件INSIDE。 FOO_CREATE()s的序列将用于根据刚刚定义的宏生成数组元素
--
输出
我使用 preprocessor-only 选项编译,在我的情况下使用
gcc PreprocessorTypePopulation.c -E -P
(-P 选项从输出中删除 linemarkers)然后我获得了以下输出(我刚刚删除了与包含的标准头相关的所有内容):
typedef enum {
my_name_FOO,
my_name2_FOO,
FOO_COUNT
} foo_id;
struct foo {
char *name;
int (*validate)(short *data, int size);
short value;
short changed;
foo_id id;
};
typedef struct foo foo_t;
int my_validate(short *data, int size)
{
return 0;
}
static foo_t foo[FOO_COUNT] = {
{ .name = "my_name", .validate = my_validate, .value = 0, .changed = 0, .id = my_name_FOO },
{ .name = "my_name2", .validate = NULL, .value = 0, .changed = 0, .id = my_name2_FOO },
}
int main(void)
{
return 0;
}
--
总之,它肯定不是一个好看的解决方案。但是它有效,它可以防止很多人为错误将多个定义集中在一个文件中。在长期的大型项目中,这可以节省数周的工作量。