Инициализация структуры через чрезмерное использование макросов - PullRequest
0 голосов
/ 16 июля 2010

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

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

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;

Это позволяет мне записывать функции и отдельные функции как (файл .c):

ON_BUTTON(blah) { ... }

и меню как (файл .h):

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

Есть ли способ сложить определение меню в одно определение?Конечно, я мог бы сделать что-то, что расширяет MENU(blah, menu_frame_blah_button, NULL, menu_frame_blah_display, NULL), но есть ли способ:

  • сделать его короче (NULL или какое-нибудь имя)
  • убрать необходимость ON_BUTTON(...);до структуры

В идеале я бы хотел, чтобы MENU(blah, button, NULL, display, NULL) определял как обработчики, так и саму структуру меню.Например, я не знаю, как предотвратить расширение последнего слагаемого на ON_SWITCH(NULL).

Или, может быть, я должен подойти к нему как-то иначе?

Ответы [ 3 ]

1 голос
/ 16 июля 2010

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

0 голосов
/ 16 июля 2010

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

С помощью таких методов вы можете написать сложные макросы, но они просты в использовании. Это становится немного проще для реализации при использовании C99 вместо C89 (вы назвали инициализаторы и VA_ARGS ), но все же.

0 голосов
/ 16 июля 2010

Вы не можете сделать условное расширение макроса в C, так что ваш макрос будет раскрываться по-разному в зависимости от аргументов, например: вы не можете использовать #if в определении макроса.

Я думаю, лучшее, что вы могли бы получитьбыло бы что-то вроде MENU(blah, ITEM(blah,button), NULL, ITEM(blah,display), NULL), и вам все еще нужен отдельный набор для прототипов из-за отсутствия условного расширения.

Лично я написал бы простой скрипт для генерации такого рода стандартного кода C.Тот, который будет понимать ваш желаемый синтаксис.В Python или как вам больше нравится ...

...