Domanda

Ho alcune strutture da inizializzare, il che sarebbe noioso da fare manualmente.Mi piacerebbe creare una macro che mi aiuterà con esso...ma non sono sicuro che il C il preprocessore è abbastanza buono per questo.

Ho strutture che rappresentano i menu.Sono costituiti solo da puntatori di funzione:

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;

Questo mi permette di scrivere le funzioni e le funzioni separate come (.file c):

ON_BUTTON(blah) { ... }

e menu come (.file h):

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

C'è un modo in cui posso piegare la definizione del menu in una definizione?Potrei fare qualcosa che si espande MENU(blah, menu_frame_blah_button, NULL, menu_frame_blah_display, NULL) certo, ma c'è un modo per:

  • rendilo più breve (NULL o qualche nome)
  • rimuovere la necessità di ON_BUTTON(...); da prima della struct

Idealmente, mi piacerebbe MENU(blah, button, NULL, display, NULL) per definire entrambi i gestori e la struttura del menu stessa.Non so per esempio come evitare di espandere l'ultimo termine in ON_SWITCH(NULL).

O forse dovrei avvicinarmi da qualche altro modo?

È stato utile?

Soluzione

Non è possibile eseguire l'espansione macro condizionale in C, in modo che la macro venga espansa in modo diverso a seconda degli argomenti, come in:non è possibile utilizzare #se all'interno della definizione di macro.

Credo che il meglio che si potrebbe ottenere sarebbe qualcosa di simile MENU(blah, ITEM(blah,button), NULL, ITEM(blah,display), NULL), e ancora ha bisogno di un insieme separato per prototipi a causa di mancanza di espansione condizionale.

Personalmente, scriverei un semplice script per generare quel tipo di codice C boilerplate.Uno che capirebbe la sintassi desiderata.In Python o quello che ti si addice meglio…

Altri suggerimenti

Ho scritto script Python per generare questo tipo di codice per me prima.Potresti voler seguire quella strada e semplicemente lavorare lo script nel tuo processo di compilazione.

È possibile programmare condizionali, cicli finiti, argomenti predefiniti e tutte queste cose nel solo preprocessore.La libreria Boost ha un'implementazione di alcuni di questi nella loro sezione preprocessore.Boost è principalmente per C++, ma le cose del preprocessore dovrebbero fondamentalmente funzionare anche in C.

Con tali tecniche è possibile scrivere macro complicate ma che sono semplici da usare.Diventa un po ' più semplice da implementare quando si utilizza C99 invece di C89 (hai chiamato inizializzatori e VA_ARGS), ma ancora.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top