Question

J'ai quelques structures à initialiser, ce qui serait fastidieux à faire manuellement.J'aimerais créer une macro qui m'aidera...mais je ne suis pas sûr que C le préprocesseur est assez bon pour cela.

J'ai des structures qui représentent des menus.Ils sont constitués uniquement de pointeurs de fonction :

typedef uint8_t (*button_handler) (uint8_t);
typedef void (*pedal_handler) (void);
typedef void (*display_handler) (void);
typedef void (*menu_switch_handler) (void);

#define ON_BUTTON(x) uint8_t menu_frame_##x##_button (uint8_t button)
#define ON_PEDAL(x) void menu_frame_##x##_pedal (void)
#define ON_DISPLAY(x) void menu_frame_##x##_display (void)
#define ON_SWITCH(x) void menu_frame_##x##_switch (void)

typedef struct menu_frame {
   button_handler on_button;
   pedal_handler on_pedal;
   display_handler on_display;
   menu_switch_handler on_switch;
} menu_frame;

Cela me permet d'écrire les fonctions et les fonctions séparées sous forme de (fichier .c) :

ON_BUTTON(blah) { ... }

et les menus sous forme de (fichier .h) :

ON_BUTTON(blah);
ON_DISPLAY(blah);
menu_frame menu_frame_blah = {
   menu_frame_blah_button,
   NULL,
   menu_frame_blah_display,
   NULL
};

Existe-t-il un moyen de regrouper la définition du menu en une seule définition ?Je pourrais faire quelque chose qui s'étend MENU(blah, menu_frame_blah_button, NULL, menu_frame_blah_display, NULL) bien sûr, mais existe-t-il un moyen de :

  • rendez-le plus court (NULL ou un autre nom)
  • supprimer le besoin de ON_BUTTON(...); d'avant la structure

Idéalement, j'aimerais MENU(blah, button, NULL, display, NULL) pour définir à la fois les gestionnaires et la structure de menu elle-même.Je ne sais pas par exemple comment empêcher d'étendre le dernier terme en ON_SWITCH(NULL).

Ou peut-être devrais-je l’aborder d’une autre manière ?

Était-ce utile?

La solution

Vous ne pouvez pas effectuer d'expansion de macro conditionnelle en C, de sorte que votre macro soit développée différemment en fonction des arguments, comme dans :vous ne pouvez pas utiliser #if dans la définition de la macro.

Je suppose que le mieux que tu puisses obtenir serait quelque chose comme MENU(blah, ITEM(blah,button), NULL, ITEM(blah,display), NULL), et vous avez toujours besoin d'un ensemble séparé pour les prototypes en raison du manque d'expansion conditionnelle.

Personnellement, j'écrirais un script simple pour générer ce type de code C passe-partout.Celui qui comprendrait la syntaxe souhaitée.En Python ou ce qui vous convient le mieux…

Autres conseils

J'ai déjà écrit des scripts Python pour générer ce type de code pour moi.Vous souhaiterez peut-être suivre cette voie et simplement intégrer le script dans votre processus de construction.

Vous pouvez programmer des conditions, des boucles finies, des arguments par défaut et tout ce genre de choses dans le seul préprocesseur.La bibliothèque Boost en a une implémentation dans sa section préprocesseur.Boost est principalement destiné au C++, mais les éléments du préprocesseur devraient également fonctionner en C.

Grâce à de telles techniques, vous pouvez écrire des macros compliquées mais simples à utiliser.Cela devient un peu plus simple à implémenter en utilisant C99 au lieu de C89 (vous avez nommé les initialiseurs et VA_ARGS), mais reste.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top