Как глобально определить переменную препроцессора?

Я программирую скетч Arduino на C++. Я хочу, чтобы пользователь мог #defineконстанту прямо в файле sketch.ino, который будет необходим для компиляции кода. Arduino IDE использует компилятор g++.

Предположим, у нас есть три файла:

sketch.ino
sketch.h
sketch.cpp

В sketch.h я определил

#define OPTION_1 0
#define OPTION_2 1
#define OPTION_3 2
#define OPTION_4 3
#define SLOW 0
#define FAST 1

Затем в sketch.ino пользователь определяет MYOPTION:

#define MYOPTION OPTION_2

В Sketch.h я использую переменную для определения макросов:

#if MYOPTION == OPTION_1 | MYOPTION == OPTION_2
    #define SPEED FAST
#else
    #define SPEED SLOW
#endif

В Sketch.cpp я использую его для улучшения критичного ко времени кода:

MyClass::foo() {
    // do something
    #if SPEED == FAST
    // do more
    #if MYOPTION == OPTION_2
    // do something extra
    #endif
    #endif
    #if MYOPTION == OPTION_4
    // do something else
    #endif
    }

К сожалению, определение MYOPTION не распознается внутри sketch.cpp. Однако sketch.cpp распознает переменные, определенные в sketch.h. Есть ли способ определить переменные препроцессора глобально, чтобы к ним можно было получить доступ в любом файле, который их использует?


person uzumaki    schedule 29.07.2017    source источник
comment
Насколько хорош в оптимизации компилятор g++, который вы используете? Возможно, вы захотите обойти весь этот мусор препроцессора и позволить вашему компилятору позаботиться об этом, поскольку использование стандартного if с enum может сделать все это так же хорошо с гораздо меньшим беспорядком. Обычно лучше использовать const вместо #define.   -  person tadman    schedule 29.07.2017
comment
@tadman Препроцессор не может оптимизировать мой код. Код должен быть пользовательским, основанным на подключенном оборудовании. Опции, предоставляемые пользователем, определяют, какие части критической по времени функции необходимы для данного оборудования. Из-за ограничения памяти (в данном случае) Arduino Due не имеет смысла предоставлять несколько функций.   -  person uzumaki    schedule 30.07.2017
comment
Это определение MYOPTION выглядит подозрительно со знаком равенства.   -  person Robert Prévost    schedule 30.07.2017
comment
@RobertPrévost Плохо. В реальном коде знака равенства нет.   -  person uzumaki    schedule 30.07.2017
comment
Я имею в виду, что код внутри блока if (false) будет удален любым оптимизирующим компилятором. Вам действительно нужны фактические блоки типа #ifdef только в том случае, если код внутри этого блока не будет компилироваться на какой-либо платформе.   -  person tadman    schedule 30.07.2017
comment
Чтобы это работало, требуется, чтобы препроцессор имел видимость всех определений макросов в правильном порядке. Это означает, что sketch.cpp должен включать sketch.h, который, в свою очередь, должен включать sketch.ino (после определений MY_OPTION_2 и т. д., но перед #if).   -  person Peter    schedule 30.07.2017
comment
@tadman Я не уверен в этом, так как мало знаю о компиляторе.   -  person uzumaki    schedule 30.07.2017


Ответы (1)


  • Переместите определения опций в отдельный файл, например. варианты.ч. Вы также можете определить их в sketch.ino, если хотите.
  • Включите options.h в sketch.ino и sketch.h.
  • Переместите весь код, основанный на макросе MYOPTION, из sketch.cpp в sketch.h.
  • Определите MYOPTION в sketch.ino перед включением sketch.h:
#include "options.h"
#define MYOPTION OPTION_2
#include "sketch.h"

Вот пример популярной библиотеки, использующей этот метод:

https://github.com/PaulStoffregen/Encoder

Это позволяет пользователю настроить использование прерываний от скетча с помощью макросов ENCODER_DO_NOT_USE_INTERRUPTS и ENCODER_OPTIMIZE_INTERRUPTS.

person per1234    schedule 30.07.2017