gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 03:26:54 25 4
gpt4 key购买 nike

我想声明一些具有相同签名的函数,可能分布在不同的头文件中,然后使用预处理器将所有这些函数收集到一个数组指针中,并创建一个相应函数名的数组。

因此,例如,假设公共(public)签名是 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) 定义中编码的信息,并且很难将这种方法用于分布在许多 header 中的未知数量的函数,因为始终需要保留这个中央列表同步。

所以我希望有一些方法可以让 FUNC 宏自动生成列表。

它也没有 编译时构造的数组,如图所示。任何允许我迭代函数指针并获取它们的名称和可能的其他辅助信息(通过附加参数添加到 FUNC)的任何东西都可以工作,例如,在启动时初始化的链表。您可以假设所有 FUNC 宏都出现在同一个编译单元中。

虽然我对 gcc 特定的解决方案不感兴趣,例如 __attribute__((constructor))

最佳答案

这是我的尝试,主要是为了解决您的问题。
它只是 x-macros 的最小改编。但不同之处可能只是让它对你有用:

  • 实际的功能代码保留在分布式 header 中。
  • 核心列表只需要适应这些功能的总数
    (和他们的名字,如果他们不是单字母字母),
    即它不反射(reflect)功能。
  • 适应大量功能不需要编辑核心实现。

这是代码,全部在一个"file"中,并带有文件拆分位置的提示。

/* 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",
""
}

我在数组中添加了最后一个条目,以避免它们的初始化以“,”结尾。但我认为大多数编译器实际上会允许这样做。
我希望编译器将 "Func""a" 替换为 "Funca"。我不喜欢短标识符。如果您的编译器没有按预期运行,请删除所有位置的“Func”并要求 ID 足够长。

展开的宏永远不会有漂亮的缩进...

关于通过不同的宏调用收集函数指针和其他辅助数据的列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40444656/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com