Создать таблицу регистрации функций отправки для нескольких исходных файлов в C

Как я могу реализовать динамическую таблицу диспетчеризации в C

По сути, это тот же вопрос, что и связанный вопрос, так что...

Поскольку ваш Strategy.c, очевидно, уже знает об экземплярах стратегии по имени (#include "XYstrategy.h") вы можете пройти целую милю и использовать заголовочные файлы вместо файлов реализации, чтобы сообщить о своей стратегии центральному диспетчеру:

Это противоречит ясному намерению в этом вопросе. Это был пример того, как он мог делать это статически, но хотел, чтобы модули динамически регистрировали себя во время компиляции.

Позвольте мне привести пример, с которым я борюсь в своих целях...

У меня есть микроконтроллер, который я хочу использовать для считывания различных датчиков, которые сообщают о температуре и / или влажности. У меня есть центральная базовая программа, которая заботится о форматировании возвращаемых данных и отправке их на веб-сервер, где они записываются в RRD.

Вместо того, чтобы создавать большую монолитную программу, которая содержит все различные функции для каждого типа датчика, я хочу иметь возможность встроить определенное подмножество в программное обеспечение, загруженное в микроконтроллер, которое соответствует датчикам, установленным на этом конкретном контроллере.

Для этого я бы хотел написать общий драйвер для каждого датчика, который имеет три функции:

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 датчики для чтения с их результатами, хранящимися в массивах, на которые указывает temp а также humidityсоответственно. Количество считанных датчиков будет сохранено в count,

sensor_shutdown Функция будет выполнять любую уборку, необходимую для возврата датчиков и вспомогательной электроники в конфигурацию с наименьшим энергопотреблением.

Каждый из них содержится в отдельном файле.c, который может иметь соответствующий файл.h для определения соответствующих констант, вызова соответствующих библиотек и т. Д.

Я хотел бы иметь основной файл Sensor.h, который включен в файлы.c или.h и который определяет:

typedef struct { startup_func, read_func, shutdown_func } sensor_driver_entry;

extern sensor_driver_entry sensor_table[];

Тогда я бы хотел, чтобы каждый файл драйвера мог использовать макрос (или функцию) для регистрации специфических для типа функций в следующем открытом слоте в sensor_table во время компиляции.

Я бы хотел, чтобы таблица датчиков была объявлена ​​в глобальном пространстве имен Sensor.c как:

sensor_driver_entry sensor_table[MAX_SENSOR_TYPES];

(MAX_SENSOR_TYPES будет определен в Sensor.h, отражая максимально возможное количество драйверов, которые могут быть выбраны).

Это вообще возможно? Если да, может ли кто-нибудь привести синтаксический пример? В этом конкретном случае я кодирую в среде Particle Dev для Particle Photon, но мне бы хотелось, чтобы я мог сделать код также переносимым в Arduino IDE, чтобы использовать его и с платами ESP8266.

1 ответ

Одной из возможностей является использование конструкторов. Ниже приведен простой пример, когда два драйвера регистрируют свои функции соответственно.

Если приложение скомпилировано с обоими драйверами (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 <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

#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

#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;
}
Другие вопросы по тегам