Создать таблицу регистрации функций отправки для нескольких исходных файлов в 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;
}