2013-06-26 57 views
2

我有一個簡單的命令行界面在我的AVR微控制器固件,根據各地的結構是這樣的:CLI命令表GCC

typedef struct { 
    const char *name; 
    const char *usage; 
    const char *help; 
    void (*handler)(char **last); 
} command_t; 

extern command_t *cli_commands[]; 

我希望能在聲明中不同模塊的命令儘可能幹。到目前爲止,我有這樣我定義我的功能是這樣的:

COMMAND_IMPL(replay, "replay <n>", "Replay frame n") { 
    // 'last' argument is for strtok_t 
} 

,然後我必須有這個在我.c文件之一:

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)。我在想,也許我可以將命令條目放在不同的部分,並將其鏈接到已知的某個地方,但我不知道它會如何終止。

回答

1

您可以使用section屬性像這樣(這是Linux內核是如何導出它的功能):

#define COMMAND_IMPL(name, usage, help) \ 
    static void cli_handle_##name##_command(char **); \ 
    command_t cli_##name##_command __attribute((section("commands"))) = { #name, usage, help, cli_handle_##name##_command }; \ 
static void cli_handle_##name##_command(char **last) 

然後,你可以使用一個ld腳本(參見http://www.math.utah.edu/docs/info/ld_3.html)獲得的地址開始所述 '命令' 部分的/端:

... 
SECTION commands ALIGN(4) : { 
    commands_begin = .; 
    *(commands) 
    commands_end = .; 
} 

最後,聲明兩個變量:

extern command_t commands_begin, commands_end;

然後,您可以使用這些變量的地址,以獲得指揮結構的整個列表,即

for (command_t *cmd = &commands_begin; cmd != &commands_end; cmd++) 
    ... 

注意如何&commands_end點只是超出了最後的命令。

+1

請注意,您不需要此鏈接器腳本。海灣合作委員會將使2個符號可用於您的部分。您可以簡單地聲明'extern command_t * __ start_commands;'和'extern command_t * __ stop_commands;'來獲取指向創建的「commands」部分的開頭和結尾的指針。 – nos

+0

如何控制該部分進入哪個部分?我需要它進入文本段(我認爲 - 這是AVR pgmspace數據)。 – Derecho

+0

我從ld得到這個錯誤: /opt/local/lib/gcc/avr/4.7.2/../../../../avr/bin/ld:在[000000000000175a加載的部分cli_cmdtable, 0000000000001771] overlapped section .data loaded at [000000000000175a,000000000000193b] – Derecho