次のような構造に基づいて、AVR マイクロコントローラー ファームウェアに単純なコマンド ライン インターフェイスがあります。
typedef struct {
const char *name;
const char *usage;
const char *help;
void (*handler)(char **last);
} command_t;
extern command_t *cli_commands[];
可能な限り DRY の方法で、さまざまなモジュールでコマンドを宣言できるようにしたいと考えています。これまでのところ、次のように関数を定義するようにしています。
COMMAND_IMPL(replay, "replay <n>", "Replay frame n") {
// 'last' argument is for strtok_t
}
そして、これを.c
ファイルの1つに含める必要があります。
COMMAND_DECL(list);
COMMAND_DECL(clear);
COMMAND_DECL(replay);
COMMAND_TABLE
COMMAND(list)
COMMAND(clear)
COMMAND(replay)
END_COMMAND_TABLE
私のマクロは次のようになります。
#define COMMAND_IMPL(name, usage, help) \
static void cli_handle_##name##_command(char **);\
command_t cli_##name##_command = {#name, usage, help, cli_handle_##name##_command};\
static void cli_handle_##name##_command(char **last)
#define COMMAND_DECL(name) extern command_t cli_##name##_command;
#define COMMAND_TABLE command_t *cli_commands[] = {
#define COMMAND(name) ((command_t *) &cli_##name##_command),
#define END_COMMAND_TABLE NULL };
それよりもうまくできるでしょうか?このプロジェクトはすでに avr-gcc に関連付けられているため、GCC のみのソリューションであるかどうかは気にしません。リンカー機能を使用するソリューションも問題ありません (私は ELF にコンパイルしています)。コマンドエントリを別のセクションに配置して、それを既知の場所にリンクさせることができると考えていますが、その場合にどのように終了するかはわかりません.