2

次のような構造に基づいて、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 にコンパイルしています)。コマンドエントリを別のセクションに配置して、それを既知の場所にリンクさせることができると考えていますが、その場合にどのように終了するかはわかりません.

4

1 に答える 1