通过不同的宏调用收集函数指针和其他辅助数据的列表

时间:2016-11-06 00:09:46

标签: c macros c-preprocessor compile-time

我想声明一些具有相同签名的函数,可能分布在不同的头文件中,然后使用预处理器将所有这些函数收集到一个数组指针中,并创建一个相应函数名的数组。 / 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特定解决方案不感兴趣。

2 个答案:

答案 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__))