在C中跨多个源文件创建调度表注册功能 [英] Create dispatch table registering functions across multiple source files in C

查看:76
本文介绍了在C中跨多个源文件创建调度表注册功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

与链接问题本质上是相同的问题,所以...

It's essentially the same question as the linked issue, so ...


您的Strategy.c显然已经知道该策略的
实例名称( #include XYstrategy.h )您可以花整整
的努力,并使用头文件而不是实现文件来
将您的策略​​传达给中央调度员:

As your Strategy.c obviously already knows about the strategy instances by name (#include "XYstrategy.h") you could go the whole mile and use the header files instead of the implementation files to communicate your strategy to the central dispatcher:

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

This is contrary to the clear intent in the question. This was an example of how he could do it statically, but wanted to have modules dynamically register themselves at compile time.

让我尝试提供一个我正在苦苦挣扎的示例出于我自己的目的...

Let me try providing an example I'm struggling with for my own purposes...

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

I have a micro-controller which I want to use to read a variety of sensors that report temperature and/or humidity. I have a central core program which takes care of formatting the returned data and submitting it to a web server where it is recorded in an RRD.

而不是构建大型的整体程序该程序包含每种传感器类型的所有不同功能,我希望能够在装入微控制器的软件中建立一个特定的子集,该软件与安装在该特定控制器上的传感器相对应。

Rather than build a large monolithic program which contains all the different functions for each sensor type, I want to be able to build a specific subset into the software loaded onto the micro-controller which corresponds to the sensors installed on that particular controller.

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

To do this I would like to be able to write a generic driver for each sensor that has three functions:

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

The sensor_startup function will take care of powering up the sensors, making sure that they are properly configured and in a state of readiness for read_sensor to be called. If this process fails for any reason, it returns false, otherwise, it returns true.

read_sensor 函数将导致最多读取 max_count 个传感器及其结果存储在分别指向 temp 湿度的数组中。读取的传感器数量将存储在 count 中。

The read_sensor function will cause up to max_count sensors to be read with their reults stored in the arrays pointed to by temp and humidity, respectively. The number of sensors read will be stored in count.

sensor_shutdown 函数将执行所有必要的内务处理,以使传感器和支持的电子设备恢复到最低功耗配置。

The sensor_shutdown function will do any housekeeping necessary to return the sensors and supporting electronics into their lowest power consumption configuration.

每个功能都包含在单独的.c文件中

Each of these is contained in a separate .c file which may have a corresponding .h file to define relevant constants, call relevant libraries, etc.

我想要一个主Sensor.h文件,该文件包含在其中,该文件可以定义相关常量,调用相关库等。 .c或.h文件,它们定义如下:

I'd like to have a master Sensor.h file which is included by the .c or .h files and which defines:

typedef struct { startup_func, read_func, shutdown_func } sensor_driver_entry;

extern sensor_driver_entry sensor_table[];

然后,我希望每个驱动程序文件都可以使用宏(或函数)来在编译时,将特定类型的函数注册到sensor_table的下一个空槽中。

Then I'd like each Driver file to be able to use a macro (or a function) to register the type-specific functions in the next open slot in sensor_table at compile time.

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

I'd like sensor table to be declared in the global namespace of Sensor.c as:

sensor_driver_entry sensor_table[MAX_SENSOR_TYPES];

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

(MAX_SENSOR_TYPES would be defined in Sensor.h reflecting the maximum possible number of drivers that could be selected).

这是否可能?如果是这样,有人可以提供一个语法示例吗?在这种特定情况下,我正在为粒子光子在Particle Dev环境中进行编码,但是如果我可以将代码也移植到Arduino IDE中,并与ESP8266板一起使用,我会很希望。

Is this even possible? If so, can someone provide a syntactic example? In this specific case, I'm coding in the Particle Dev environment for a Particle Photon, but I'd like it if I could make the code also portable to the Arduino IDE to use it with ESP8266 boards as well.

推荐答案

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

One possibility is to make use of constructors. Below is a simple example with two drivers registering their functions respectively.

如果应用程序是使用两个驱动程序编译的( gcc main.c driver1.c driver2.c )输出显示了已注册的两个驱动程序功能:

If the application is compiled with both drivers (gcc main.c driver1.c driver2.c) the output shows both driver functions registered:

driver1_init
driver2_init
driver1_func
driver2_func

如果仅第一个驱动程序在( gcc main.c driver1.c )输出仅显示已注册的驱动程序功能:

If only the first driver is compiled in (gcc main.c driver1.c) the output shows only that driver's function registered:

driver1_init
driver1_func



driver.h



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



main.c

#include <stdio.h>
#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



driver1.c

#include <stdio.h>
#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



driver2.c

#include <stdio.h>
#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;
}

这篇关于在C中跨多个源文件创建调度表注册功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆