我想声明一些具有相同签名的函数,可能分布在不同的头文件中,然后使用预处理器将所有这些函数收集到一个数组指针中,并创建一个相应函数名的数组。 / p>
因此,例如,假设共同签名是int func(int x)
我可以有以下声明:
FUNC(a) {
return x + x;
}
FUNC(b) {
return x >> 1;
}
FUNC(c) {
return x ^ 123;
}
...通过一些宏观魔法,我会在预处理之后看到一些东西:
int a(int x) {
return x + x;
}
int b(int x) {
return x >> 1;
}
int c(int x) {
return x ^ 123;
}
typedef int (*intfunc_t)(int)
const intfunc_t func_ptrs[] = { &a, &b, &c };
const char *func_names[] = { "a", "b", "c" };
使用x-macros可以实现更糟糕的版本,但这需要一个类似的列表:
#define X_MACRO \
X(a) \
X(b) \
X(c)
这复制了FUNC(a)
定义中已经编码的信息,并且很难使用这种方法,并且在许多标题中分布了未知数量的函数,因为这个中心列表总是需要保持同步。
所以我希望有一些方法让FUNC
宏自动生成列表。
它也没有 编译时构造的数组,如图所示。任何允许我迭代函数指针,并获取其名称和可能的其他辅助信息(通过附加args添加到FUNC
)的任何东西都可以工作,例如,在启动时初始化的链表。您可以假设所有FUNC
宏都出现在同一个编译单元中。
虽然我对像__attribute__((constructor))
这样的gcc特定解决方案不感兴趣。
答案 0 :(得分:1)
这是我尝试解决你的问题 它只是x-macros的最小调整。 但差异可能只会使它对你有用:
这是代码,全部在一个"文件",带有提示文件被拆分。
/* content of distributed header a.h */
#define FUNC_a_Implementation() \
{ \
return x+x; \
}
/* content of distributed header b.h */
#define FUNC_b_Implementation() \
{ \
return x>>1 ; \
}
/* content of distributed header c.h */
#define FUNC_c_Implementation() \
{ \
return ParCode; \
}
/* content of core editable header */
/* #include here the headers a.h, b.h c.h
potentially d.h, e.h and f.h in the future
*/
#define MAGIC_LIST(ParFlavor) \
ENTRY_##ParFlavor(a) \
ENTRY_##ParFlavor(b) \
ENTRY_##ParFlavor(c) \
/* add these when needed
ENTRY_##ParFlavor(d) \
ENTRY_##ParFlavor(e) \
ENTRY_##ParFlavor(f) \
*/
/* content of core implementation */
/* include editable core header */
#define ENTRY_Implementation(ParId) \
int Func##ParId (int x) \
FUNC_##ParId##_Implementation()
#define ENTRY_Pointer(ParId) \
&Func##ParId,
#define ENTRY_Name(ParId) \
"Func"#ParId,
MAGIC_LIST(Implementation)
const intfunc_t func_ptrs[] = {
MAGIC_LIST(Pointer)
NULL
}
const char *func_names[] = {
MAGIC_LIST(Name)
""
}
预处理时,结果为:
$MinGW\bin\gcc -E macros.c
# 1 "macros.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "macros.c"
# 50 "macros.c"
int Funca (int x) { return x+x; } int Funcb (int x) { return x>>1 ; } int Funcc (int x) { return x^123; }
const intfunc_t func_ptrs[] = {
&Funca, &Funcb, &Funcc,
NULL
}
const char *func_names[] = {
"Func""a", "Func""b", "Func""c",
""
}
我在数组中添加了最后一个条目,以避免它们的初始化结束于&#34;,#34;。但我认为大多数编译器实际上都允许这样做
我希望编译器将"Func""a"
替换为"Funca"
。我不喜欢短标识符。如果您的编译器未按预期执行,请删除&#34; Func&#34;无处不在,要求Ids足够长。
扩展的宏永远不会有漂亮的缩进...
答案 1 :(得分:0)
我有一个带有函数typedef的头文件和原型:
//the_header.h
typedef int intfunc_t(int); /*function not function pointer*/
intfunc_t a,b,c; /*prototypes*/
将其包含在每个实现文件中,然后将一个文件包含在:
#include "the_header.h"
const intfunc_t *func_ptrs[] = { a,b,c };
const char *func_names[] = { "a","b","c" };
虽然可以删除a,b,c复制并具有类似的内容:
//the_header.h
typedef int intfunc_t(int); /*function not function pointer*/
#define FUNC a,b,c
intfunc_t FUNCS; /*prototypes*/
//collector.c
#include "the_header.h"
const intfunc_t *func_ptrs[] = { FUNCS };
const char *func_names[] = { STRINGIFY_EACH(FUNCS) };
实现STRINGIFY_EACH需要一些暗宏魔法(AFAIK),例如:
#define STRINGIFY_EACH(...) MC_foreachc(MC_str, __VA_ARGS__)
#define MC_str(_d) MC_str_impl_(_d)
#define MC_str_impl_(s) #s
#define MC_foreachc(What, ...) MC_foreachc_(MC_argc(__VA_ARGS__), What, __VA_ARGS__)
/* MC_foreachc(foo, a,b,c) foo(a), foo(b), foo(c); */
#define MC_foreachc_0( What, x, ...)
#define MC_foreachc_1( What, x, ...) What(x)
#define MC_foreachc_2( What, x, ...) What(x) , MC_expand(MC_foreachc_1( What, __VA_ARGS__))
#define MC_foreachc_3( What, x, ...) What(x) , MC_expand(MC_foreachc_2( What, __VA_ARGS__))
#define MC_foreachc_4( What, x, ...) What(x) , MC_expand(MC_foreachc_3( What, __VA_ARGS__))
#define MC_foreachc_5( What, x, ...) What(x) , MC_expand(MC_foreachc_4( What, __VA_ARGS__))
#define MC_foreachc_6( What, x, ...) What(x) , MC_expand(MC_foreachc_5( What, __VA_ARGS__))
#define MC_foreachc_7( What, x, ...) What(x) , MC_expand(MC_foreachc_6( What, __VA_ARGS__))
#define MC_foreachc_8( What, x, ...) What(x) , MC_expand(MC_foreachc_7( What, __VA_ARGS__))
#define MC_foreachc_9( What, x, ...) What(x) , MC_expand(MC_foreachc_8( What, __VA_ARGS__))
#define MC_foreachc_10( What, x, ...) What(x) , MC_expand(MC_foreachc_9( What, __VA_ARGS__))
#define MC_foreachc_11( What, x, ...) What(x) , MC_expand(MC_foreachc_10( What, __VA_ARGS__))
#define MC_foreachc_12( What, x, ...) What(x) , MC_expand(MC_foreachc_11( What, __VA_ARGS__))
#define MC_foreachc_13( What, x, ...) What(x) , MC_expand(MC_foreachc_12( What, __VA_ARGS__))
#define MC_foreachc_14( What, x, ...) What(x) , MC_expand(MC_foreachc_13( What, __VA_ARGS__))
#define MC_foreachc_15( What, x, ...) What(x) , MC_expand(MC_foreachc_14( What, __VA_ARGS__))
#define MC_foreachc_16( What, x, ...) What(x) , MC_expand(MC_foreachc_15( What, __VA_ARGS__))
#define MC_foreachc_17( What, x, ...) What(x) , MC_expand(MC_foreachc_16( What, __VA_ARGS__))
#define MC_foreachc_18( What, x, ...) What(x) , MC_expand(MC_foreachc_17( What, __VA_ARGS__))
#define MC_foreachc_19( What, x, ...) What(x) , MC_expand(MC_foreachc_18( What, __VA_ARGS__))
#define MC_foreachc_20( What, x, ...) What(x) , MC_expand(MC_foreachc_19( What, __VA_ARGS__))
#define MC_foreachc_21( What, x, ...) What(x) , MC_expand(MC_foreachc_20( What, __VA_ARGS__))
#define MC_foreachc_22( What, x, ...) What(x) , MC_expand(MC_foreachc_21( What, __VA_ARGS__))
#define MC_foreachc_23( What, x, ...) What(x) , MC_expand(MC_foreachc_22( What, __VA_ARGS__))
#define MC_foreachc_24( What, x, ...) What(x) , MC_expand(MC_foreachc_23( What, __VA_ARGS__))
#define MC_foreachc_25( What, x, ...) What(x) , MC_expand(MC_foreachc_24( What, __VA_ARGS__))
#define MC_foreachc_26( What, x, ...) What(x) , MC_expand(MC_foreachc_25( What, __VA_ARGS__))
#define MC_foreachc_27( What, x, ...) What(x) , MC_expand(MC_foreachc_26( What, __VA_ARGS__))
#define MC_foreachc_28( What, x, ...) What(x) , MC_expand(MC_foreachc_27( What, __VA_ARGS__))
#define MC_foreachc_29( What, x, ...) What(x) , MC_expand(MC_foreachc_28( What, __VA_ARGS__))
#define MC_foreachc_30( What, x, ...) What(x) , MC_expand(MC_foreachc_29( What, __VA_ARGS__))
#define MC_foreachc_31( What, x, ...) What(x) , MC_expand(MC_foreachc_30( What, __VA_ARGS__))
#define MC_foreachc_32( What, x, ...) What(x) , MC_expand(MC_foreachc_31( What, __VA_ARGS__))
#define MC_foreachc_(N, What, ...) MC_expand(MC_cat(MC_foreachc_, N)( What, __VA_ARGS__))