在C中创建跨多个源文件注册函数的调度表

如何在C中实现动态调度表

它与链接问题基本上是同一个问题,所以……

由于您的Strategy.c显然已经知道了名称( #include "XYstrategy.h" )的策略实例,您可以全力以赴,使用头文件而不是实现文件将您的策略​​传达给中央调度员:

这与问题中的明确意图相反。 这是他如何静态地执行此操作的示例,但希望模块在编译时动态注册。

让我试着提供一个我为自己的目的而奋斗的例子……

我有一个微控制器,我想用它来读取报告温度和/或湿度的各种传感器。 我有一个中央核心程序,负责格式化返回的数据并将其提交到Web服务器,在那里它被记录在RRD中。

我希望能够在加载到微控制器上的软件中构建一个特定的子集,而不是构建包含每种传感器类型的所有不同function的大型单片程序,该控制器对应于安装在该特定控制器上的传感器。

为此,我希望能够为每个具有三个function的传感器编写通用驱动程序:

 bool _sensor_startup(); bool _read_sensor(float *temp, float *humidity, uint8_t max_count, uint8_t *count); bool _sensor_shutdown(); 

sensor_startup函数将负责为传感器供电,确保它们已正确配置并处于准备好read_sensor的状态。 如果此进程因任何原因失败,则返回false ,否则返回true

read_sensor函数将导致最多读取max_count传感器,其结果分别存储在由temphumidity指向的数组中。 读取的传感器数量将存储在count

sensor_shutdownfunction将执行将传感器和支持电子设备返回其最低功耗配置所需的任何内务处理。

其中每个都包含在一个单独的.c文件中,该文件可能有相应的.h文件来定义相关常量,调用相关库等。

我希望有一个主文件Sensor.h文件,它包含在.c或.h文件中,它定义了:

 typedef struct { startup_func, read_func, shutdown_func } sensor_driver_entry; extern sensor_driver_entry sensor_table[]; 

然后我希望每个Driver文件能够使用宏(或函数)在编译时在sensor_table的下一个打开的槽中注册特定于类型的函数。

我希望传感器表在Sensor.c的全局命名空间中声明为:

 sensor_driver_entry sensor_table[MAX_SENSOR_TYPES]; 

MAX_SENSOR_TYPES将在Sensor.h中定义,反映可以选择的最大可能驱动程序数)。

这有可能吗? 如果是这样,有人可以提供一个语法示例吗? 在这个特定的情况下,我在粒子开发环境中为粒子光子编码,但是如果我能使代码也可以移植到Arduino IDE以便与ESP8266板一起使用,我也会喜欢它。

一种可能性是利用构造函数。 下面是一个简单的例子,两个驱动程序分别注册它们的函数。

如果使用两个驱动程序( gcc main.c driver1.c driver2.c )编译应用程序,则输出显示已注册的两个驱动程序函数:

 driver1_init driver2_init driver1_func driver2_func 

如果仅在( gcc main.c driver1.c )中编译第一个驱动程序,则输出仅显示已注册的驱动程序的函数:

 driver1_init driver1_func 

driver.h

 typedef void (*driver_func_t)(void); typedef struct { driver_func_t func; } driver_entry_t; #define MAX_TYPES 10 extern driver_entry_t driver_table[MAX_TYPES]; extern unsigned int num_driver_entries; 

main.c中

 #include  #include "driver.h" driver_entry_t driver_table[MAX_TYPES]; unsigned int num_driver_entries; int main (void) { unsigned int ix; for (ix = 0; ix < num_driver_entries; ix++) { driver_table[ix].func(); } return 0; } 

driver1.c

 #include  #include "driver.h" void driver1_func (void) { printf("%s\n", __FUNCTION__); } void driver1_init (void) __attribute__ ((constructor)); void driver1_init (void) { printf("%s\n", __FUNCTION__); driver_table[num_driver_entries++].func = driver1_func; } 

driver2.c

 #include  #include "driver.h" void driver2_func (void) { printf("%s\n", __FUNCTION__); } void driver2_init (void) __attribute__ ((constructor)); void driver2_init (void) { printf("%s\n", __FUNCTION__); driver_table[num_driver_entries++].func = driver2_func; }