Простая идея:
Я использую X-макросы для определения структуры списка команд и объявления обратных вызовов команд.
#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;
}
это работает.
helloworld
help!
Добавление некоторых параметров:
Если вы измените первый список команд на это (добавив параметры)
#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-макроса избежать этой ошибки?
Я думал о немакро-способе маскировки неиспользуемых параметров:
, используя (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)) \
Может быть, истина в другом месте ...:)
есть намеки?