我正在开发一个嵌入式应用程序,通过命令界面控制设备.我嘲笑VC中的指挥调度员,让我满意; 但是当我将代码移到嵌入式环境中时,我发现编译器的指针到func的实现方式已经破碎了.
这是我最初实现代码的方式(在VC中):
/* Relevant parts of header file */ typedef struct command { const char *code; void *set_dispatcher; void *get_dispatcher; const char *_description; } command_t; #define COMMAND_ENTRY(label,dispatcher,description) {(const char*)label, &set_##dispatcher, &get_##dispatcher, (const char*)description} /* Dispatcher data structure in the C file */ const command_t commands[] = { COMMAND_ENTRY("DH", Dhcp, "DHCP (0=off, 1=on)"), COMMAND_ENTRY("IP", Ip, "IP Address (192.168.1.205)"), COMMAND_ENTRY("SM", Subnet, "Subunet Mask (255.255.255.0)"), COMMAND_ENTRY("DR", DefaultRoute, "Default router (192.168.1.1)"), COMMAND_ENTRY("UN", Username, "Web username"), COMMAND_ENTRY("PW", Password, "Web password"), ... } /* After matching the received command string to the command "label", the command is dispatched */ if (pc->isGetter) return ((get_fn_t)(commands[i].get_dispatcher))(pc); else return ((set_fn_t)(commands[i].set_dispatcher))(pc); }
在不使用函数指针的情况下,似乎我唯一的希望是使用switch()/ case语句来调用函数.但我想避免手动维护一个大的switch()语句.
我想做的是将所有COMMAND_ENTRY行移动到一个单独的包含文件中.然后包含包含不同#define和#undefines文件的包装.就像是:
/* Create enum's labels */ #define COMMAND_ENTRY(label,dispatcher,description) SET_##dispatcher, GET_##dispatcher typedef enum command_labels = { #include "entries.cinc" DUMMY_ENUM_ENTRY} command_labels_t; #undefine COMMAND_ENTRY /* Create command mapping table */ #define COMMAND_ENTRY(label,dispatcher,description) {(const char*)label, SET_##dispatcher, GET_##dispatcher, (const char*)description} const command_t commands[] = { #include "entries.cinc" NULL /* dummy */ }; #undefine COMMAND_ENTRY /*...*/ int command_dispatcher(command_labels_t dispatcher_id) { /* Create dispatcher switch statement */ #define COMMAND_ENTRY(label,dispatcher,description) case SET_##dispatcher: return set_##dispatcher(pc); case GET_##dispatcher: return get_##dispatcher(pc); switch(dispatcher_id) { #include "entries.cinc" default: return NOT_FOUND; } #undefine COMMAND_ENTRY }
有没有人看到更好的方法来处理这种情况?遗憾的是,"获得另一个编译器"不是一个可行的选择.:(
---编辑添加:为了澄清,特定的嵌入式环境被打破了,因为编译器应该创建一个"函数指针表",然后编译器使用该表来通过指针解析对函数的调用.不幸的是,编译器坏了,并且没有生成正确的函数表.
所以我没有一种简单的方法来提取func地址来调用它.
---编辑#2:啊,是的,使用void*(set | get)_dispatcher是我试图查看问题是否与func指针的typedefine有关.原来,我有
typedef int (*set_fn_t)(cmdContext_t *pCmdCtx); typedef int (*get_fn_t)(cmdContext_t *pCmdCtx); typedef struct command { const char *code; set_fn_t set_dispatcher; get_fn_t get_dispatcher; const char *_description; } command_t;
Michael Burr.. 7
您应该尝试更改您struct command
的函数指针具有实际类型:
typedef struct command { const char *code; set_fn_t set_dispatcher; get_fn_t get_dispatcher; const char *_description; } command_t;
不幸的是,函数指针不能保证能够转换为/从void指针转换(仅适用于指向对象的指针).
什么是嵌入式环境?
鉴于问题更新中发布的信息,我发现它确实是一个有问题的编译器.
我认为你提出的解决方案似乎很合理 - 它可能与我想出的相似.
您应该尝试更改您struct command
的函数指针具有实际类型:
typedef struct command { const char *code; set_fn_t set_dispatcher; get_fn_t get_dispatcher; const char *_description; } command_t;
不幸的是,函数指针不能保证能够转换为/从void指针转换(仅适用于指向对象的指针).
什么是嵌入式环境?
鉴于问题更新中发布的信息,我发现它确实是一个有问题的编译器.
我认为你提出的解决方案似乎很合理 - 它可能与我想出的相似.