【发布时间】:2020-02-24 10:11:12
【问题描述】:
简单的想法:
我正在使用 X-macros 来定义命令列表结构并声明命令回调。
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#define COMMAND_LIST(X) \
X(toto_all) \
X(help) \
//end of list
typedef void (*callback_t)(int a, int b);
typedef struct
{
char * name;
callback_t callback;
}command_t;
#define CALLBACK_DEC(COMMAND_NAME) void _##COMMAND_NAME(int a, int b);
COMMAND_LIST(CALLBACK_DEC)
#define COMMAND_DEF(COMMAND_NAME) { #COMMAND_NAME, & _##COMMAND_NAME },
static command_t commands[] =
{
COMMAND_LIST(COMMAND_DEF)
};
#define COMMAND(COMMAND_NAME,CODE) void _##COMMAND_NAME(int A, int B) { CODE }
COMMAND(toto_all,
printf("helloworld\n");
)
COMMAND(help,
printf("help!\n");
)
int main()
{
commands[0].callback(1,2);
commands[1].callback(1,2);
return 0;
}
它有效。
你好世界
帮忙!
添加一些参数:
如果将第一个命令列表更改为此(通过添加参数)
#define COMMAND_LIST(X) \
X(toto_all, 1, 3, 5) \
X(help, 0, 0, 0) \
//end of list
typedef struct
{
callback_t callback;
char * name;
int arg_min;
int arg_max;
int arg_num;
}command_t;
然后,在运行它时,我收到以下错误:
macro "CALLBACK_DEC" passed 4 arguments, but takes just 1
我必须使用命令列表定义(命令声明)的所有参数:
#define COMMAND_DEF(COMMAND_NAME, ARG_MIN, ARG_MAX, ARG_MAX, ARG_NUM) (command_t){ #COMMAND_NAME, & _##COMMAND_NAME, ARG_MIN, ARG_MAX, ARG_NUM},
但是现在将它用于回调声明非常棘手......
这个 X-macro 有没有巧妙的方法来避免这个错误?
想到了屏蔽未使用参数的非宏方式:
使用(void)param;,
这给了丑陋的
#define CALLBACK_DEC(COMMAND_NAME, ARG_MIN, ARG_MAX, ARG_NUM) void _##COMMAND_NAME(int a, int b); void(ARG_MIN); void(ARG_MAX); void(ARG_NUM)
这不起作用......我很奇怪:
main.c:27:20: error: expected identifier or ‘(’ before numeric constant
X(toto_all,0,0,0) \
我认为还有另一种方式:
也许使用类似的东西......
#define COMMAND_LIST(X,Y) \
X(Y(toto_all, 0, 0, 0)) \
X(Y(help, 0, 0, 0)) \
//command name, arg min, arg max, arg num, string?
//end of list
typedef void (*callback_t)(int a, int b);
typedef struct
{
char * name;
callback_t callback;
}command_t;
#define GET_ONLY_NAME(COMMAND_NAME1, ARG_MIN, ARG_MAX, ARG_NUM) COMMAND_NAME1
#define CALLBACK_DEC(COMMAND_NAME) void _##COMMAND_NAME(int a, int b);
COMMAND_LIST(CALLBACK_DEC,GET_ONLY_NAME);
#undef CALLBACK_DEC
#define GET_FULL_LIST(X) X
#define COMMAND_DEF(COMMAND_NAME, ARG_MIN, ARG_MAX, ARG_NUM) (command_t){ #COMMAND_NAME, & _##COMMAND_NAME, ARG_MIN, ARG_MAX, ARG_NUM},
static command_t commands[] =
{
COMMAND_LIST(COMMAND_DEF,GET_FULL_LIST)
};
#undef COMMAND_DEF
但我还是得到了以下奇怪的错误,扩展有问题但我看不到在哪里...
main.c:27:31: error: expected ‘)’ before numeric constant
X(Y(toto_all, 0, 0, 0)) \
也许真相在别处...... :)
有什么提示吗?
【问题讨论】:
-
“它有效”的版本不起作用。您在这里有一个分号:
COMMAND_LIST(CALLBACK_DEC);,但也在它上面的宏声明中。此外,您不能使用复合文字来初始化文件范围变量,因为这不是常量表达式。 (只要去掉复合文字符号就可以了。)编译代码需要哪个编译器和什么非标准设置? -
只需复制粘贴第一个代码,您就会看到它有效:onlinegdb.com/SyABNE-NL
-
好吧,默认 GNU C。可能想养成使用
-std=c11 -pedantic-errors编译的习惯,你会发现 GNU C 版本隐藏的各种错误和语法错误。 -
thanx,已在帖子中更正。这并没有回答这个问题:o)