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

标签 c function-pointers dispatcher

我正在开发一个嵌入式应用程序,其中的设备通过命令界面进行控制。我在 VC 中模拟了命令调度程序,并让它工作得让我满意;但是当我将代码移到嵌入式环境时,我发现编译器的函数指针实现有问题。

下面是我最初实现代码的方式(在 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
}

有没有人看到更好的方法来处理这种情况?可悲的是,“获得另一个编译器”不是一个可行的选择。 :(

---编辑添加: 澄清一下,特定的嵌入式环境被破坏了,因为编译器应该创建一个“函数指针表”,然后编译器使用它来通过指针解析对函数的调用。不幸的是,编译器已损坏,无法生成正确的函数表。

所以我没有一个简单的方法来提取函数地址来调用它。

--- 编辑#2: 啊,是的,使用 void *(set|get)_dispatcher 是我尝试查看问题是否与 func 指针的类型定义有关。本来,我有

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;

最佳答案

您应该尝试更改您的struct 命令,以便函数指针具有实际类型:

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

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

什么是嵌入式环境?


根据问题更新中发布的信息,我发现它确实是一个有问题的编译器。

我认为您提出的解决方案似乎很合理 - 它可能与我想出的类似。

关于c - 如果我的编译器对函数指针的支持被破坏,我该如何编写一个调度程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/284952/

相关文章:

c - 编译过程中出现错误?

c - 编译后直立矩形内有问号?

c - 父进程如何验证子进程发送的信号

c# - 通过 Dispatcher 调用异步 lambda 时双重等待

c - 需要接受用户输入并在最后全部输出

c++ - 如何使用函数指针从其内存地址调用成员函数?

c - 为什么这个指向函数的指针可以在没有警告或错误的情况下工作?

C++-17 : cast function pointer to function with different argument pointer type

.net - 从后台线程更新BindingList <>?

c# - 如何在另一个线程上渲染视觉对象