#прагма внутри #define

Я работаю в микроконтроллере, используя язык C. В этом конкретном микро прерывания должны быть определены с помощью #pragma следующим образом:

static void func();
#pragma INTERRUPT func <interrupt_address> <interrupt_category>
static void func() { /* function body */ }

<interrupt_address> — это адрес прерывания в таблице векторов. <interrupt_category> равно 1 или 2. Например, чтобы определить прерывание в порту 0, вывод 0:

static void _int_p00();
#pragma INTERRUPT _int_p00 0x10 1
static void _int_p00() { (*isr_p00)(); }

Мы определяем фактическую процедуру обработки прерывания в другом месте и используем указатель функции (например, isr_p00 в примере) для их выполнения.

Было бы удобно, если бы прерывания можно было определять с помощью макроса. Я хочу определить макрос следующим образом:

#define DECLARE_INTERRUPT(INT_NAME, INT_CAT) \
    static void _int_##INT_NAME(); \
    #pragma INTERRUPT _int_##INT_NAME INT_NAME##_ADDR INT_CAT \
    static void _int_##INT_NAME() { (*isr_##INT_NAME)(); }

Компилятор выдает следующую ошибку:

Formal parameter missing after '#'

с указанием следующей строки:

static void _int_##INT_NAME() { (*isr_##INT_NAME)(); }

Я предполагаю, что директивы препроцессора нельзя использовать в #defines? Есть ли работа вокруг?


person Donotalo    schedule 27.07.2010    source источник
comment
Какой микроконтроллер и компилятор? Если он основан на GCC, может быть специальный макрос атрибута, который вы можете использовать, например, в Microchip C32: void __ISR(_TIMER_5_VECTOR) SomeISR(void)   -  person detly    schedule 27.07.2010
comment
Микросхема — OKI 431, а компилятор — OKI: IDEU8.   -  person Donotalo    schedule 27.07.2010


Ответы (3)


C99 имеет новое ключевое слово _Pragma, которое позволяет размещать #pragma внутри макросов. По сути, он ожидает строку в качестве аргумента, которая соответствует тексту, который вы бы передали директиве #pragma.

Если ваш компилятор не поддерживает это (gcc поддерживает), и вы бы выбрали внешнюю реализацию того, что вам нужно (как было сказано, m4 может быть выбором), лучше всего, вероятно, оставаться как можно ближе к этому не- такой новый _Pragma. Затем, как только ваш компилятор догонит стандарт, вы можете просто прекратить использовать свой скрипт.

person Jens Gustedt    schedule 27.07.2010
comment
Компилятор не поддерживает _Pragma. :( - person Donotalo; 27.07.2010
comment
@ Донотало, очень плохо. этот стандарт существует всего 11 лет ;-) Вы можете попробовать смешанное решение, просто используя gcc в качестве препроцессора, а затем используя свой собственный компилятор для последующих этапов компиляции. - person Jens Gustedt; 27.07.2010

Обходной путь — использовать генерацию кода или другой макроязык для предварительной обработки кода.

т.е. написать код с другим расширением.

Сделайте так, чтобы ваш make-файл или аналогичный вызывал макроязык (например, m4) или скрипт какой-либо формы для создания файла .c.

Затем скомпилируйте это.

person mmmmmm    schedule 27.07.2010
comment
Ищете решение, которое не будет вызывать другой скрипт. - person Donotalo; 27.07.2010

Насколько мне известно, то, о чем вы конкретно спрашиваете, невозможно. Я предполагаю, что препроцессор работает так же, как препроцессор GNU C. В руководстве по этому поводу указано:

Компилятор не выполняет повторную токенизацию вывода препроцессора. Каждый токен предварительной обработки становится одним токеном компилятора.

person detly    schedule 27.07.2010
comment
Я тоже думал, что это невозможно. Но мне интересно, можно ли добиться этого каким-либо другим способом. - person Donotalo; 27.07.2010