Créer une table de répartition enregistrant des fonctions sur plusieurs fichiers sources en C

Comment puis-je implémenter une table de répartition dynamic en C

C’est essentiellement la même question que la question liée, alors …

Comme votre Strategy.c connaît évidemment déjà les instances de stratégie par leur nom ( #include "XYstrategy.h" ), vous pouvez parcourir le mille et utiliser les fichiers d’en-tête au lieu des fichiers d’implémentation pour communiquer votre stratégie au répartiteur central:

Ceci est contraire à l’intention claire de la question. C’était un exemple de la façon dont il pouvait le faire statiquement, mais il souhaitait que les modules s’enregistrent de manière dynamic au moment de la compilation.

Laissez-moi essayer de donner un exemple avec lequel je lutte pour mes propres objectives …

J’ai un micro-contrôleur que je veux utiliser pour lire divers capteurs qui signalent la température et / ou l’humidité. J’ai un programme central qui s’occupe de formater les données retournées et de les soumettre à un serveur Web où elles sont enregistrées dans un RRD.

Plutôt que de construire un grand programme monolithique contenant toutes les fonctions de chaque type de capteur, je souhaite pouvoir créer un sous-ensemble spécifique dans le logiciel chargé sur le micro-contrôleur qui correspond aux capteurs installés sur ce contrôleur particulier.

Pour ce faire, j’aimerais pouvoir écrire un pilote générique pour chaque capteur ayant trois fonctions:

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

La fonction sensor_startup se chargera de mettre les capteurs sous tension, en s’assurant qu’ils sont correctement configurés et prêts à être appelés pour que read_sensor soit appelé. Si ce processus échoue pour une raison quelconque, il renvoie false , sinon, il renvoie true .

La fonction read_sensor provoquera la max_count capteurs jusqu’à max_count avec leurs valeurs stockées dans les tableaux pointés par temp ethumidité, respectivement. Le nombre de capteurs lus sera enregistré dans le count .

La fonction sensor_shutdown fera tout le ménage nécessaire pour ramener les capteurs et les composants électroniques de support dans leur configuration avec la consommation d’énergie la plus basse.

Chacune de celles-ci est contenue dans un fichier .c séparé qui peut avoir un fichier .h correspondant pour définir les constantes pertinentes, appeler les bibliothèques pertinentes, etc.

J’aimerais avoir un fichier maître Sensor.h qui est inclus dans les fichiers .c ou .h et qui définit:

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

Ensuite, j’aimerais que chaque fichier de pilote puisse utiliser une macro (ou une fonction) pour enregistrer les fonctions spécifiques au type dans le prochain emplacement libre de sensor_table au moment de la compilation.

J’aimerais que la table de capteurs soit déclarée dans l’espace de noms global de Sensor.c en tant que:

 sensor_driver_entry sensor_table[MAX_SENSOR_TYPES]; 

( MAX_SENSOR_TYPES serait défini dans Sensor.h en fonction du nombre maximal de pilotes pouvant être sélectionnés).

Est-ce seulement possible? Si oui, quelqu’un peut-il fournir un exemple syntaxique? Dans ce cas particulier, je code dans l’environnement de développement de particules pour un photon de particules, mais j’aimerais que le code soit également portable pour l’IDE Arduino et qu’il puisse également être utilisé avec les cartes ESP8266.

Une possibilité consiste à utiliser des constructeurs. Vous trouverez ci-dessous un exemple simple dans lequel deux pilotes enregistrent leurs fonctions.

Si l’application est compilée avec les deux pilotes ( gcc main.c driver1.c driver2.c ), la sortie affiche les deux fonctions de pilote enregistrées:

 driver1_init driver2_init driver1_func driver2_func 

Si seul le premier pilote est compilé dans ( gcc main.c driver1.c ), la sortie affiche uniquement la fonction de ce pilote enregistrée:

 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_ensortinges; 

principal c

 #include  #include "driver.h" driver_entry_t driver_table[MAX_TYPES]; unsigned int num_driver_ensortinges; 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) __atsortingbute__ ((constructor)); void driver1_init (void) { printf("%s\n", __FUNCTION__); driver_table[num_driver_ensortinges++].func = driver1_func; } 

driver2.c

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