当前位置:  开发笔记 > 编程语言 > 正文

如果编译器对指针到函数的支持被破坏,我该如何编写调度程序?

如何解决《如果编译器对指针到函数的支持被破坏,我该如何编写调度程序?》经验,为你挑选了1个好方法。

我正在开发一个嵌入式应用程序,通过命令界面控制设备.我嘲笑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指针转换(仅适用于指向对象的指针).

什么是嵌入式环境?


鉴于问题更新中发布的信息,我发现它确实是一个有问题的编译器.

我认为你提出的解决方案似乎很合理 - 它可能与我想出的相似.



1> Michael Burr..:

您应该尝试更改您struct command的函数指针具有实际类型:

typedef struct command {
  const char *code;
  set_fn_t set_dispatcher;
  get_fn_t get_dispatcher;
  const char *_description;
} command_t;

不幸的是,函数指针不能保证能够转换为/从void指针转换(仅适用于指向对象的指针).

什么是嵌入式环境?


鉴于问题更新中发布的信息,我发现它确实是一个有问题的编译器.

我认为你提出的解决方案似乎很合理 - 它可能与我想出的相似.

推荐阅读
周扒pi
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有