как использовать #ifdef в CPP файле ???
- Войдите на сайт для отправки комментариев
суть проблеммы:
от основной программы отделил файл #include "A_Config.h", именно в этом файле устанавливаю #define DATE_TIME_USE (переносить установку в основной модуль очень не хочется)
далее я хочу, что-бы в CPP файла проекта (там их много) работала директива #ifdef DATE_TIME_USE
но тут проблемма, cpp файлы собираются все вместе еще до обработки #include "xxx.h" и по существу весь мой код вырезается а только потом устанавливается директива #include
какие будут предложения?
я пока вижу следующие варианты:
1. отказатся от использования файла A_Config.h и все перенести в основной файл, но мне не нравится это
2. перенести весь код CPP в H файл, но я не понимаю чем это грозит. На вскидку могут быть проблеммы с видимостью объектов...
Какую-то фигню вы написали. ВСЕ заголовочные файлы, подключённые как в *.h, так в *.cpp и в *.ino - разбираются _до_ начала обработки собственно исходников. Юзаю препроцессорные директивы в хвост и в гриву, версия IDE 1.6.7, всё прекрасно собирается.
Можете проверить на простом тесте:
1. Файл A_Config.h:
2. Файл Some.h:
#ifndef _SOME_H #define _SOME_H #include "A_Config.h" class Test { public: Test(); void out(); }; #endif3. Файл Some.cpp:
#include "Some.h" Test::Test() { } void Test::out() { #ifdef DATE_TIME_USE Serial.begin(9600); Serial.println("It's alive!"); #endif }4. Файл *.ino проекта:
#include "Some.h" void setup() { Test test; test.out(); }И прошить в МК. Если определена директива DATE_TIME_USE - то в Serial должна вывестись строка, если директиву закомментировать и пересобрать прошивку - строки не будет. Писал навскидку, думаю, принцип понятен.
ну я почти так и делал, вся разница в том, что у Вас в cpp под директиву убраны 2 строки внутри процедуры а я убирал всю процедуру целиком, и компилятор банально выдавал ошибку вне зависимости от наличия DATE_TIME_USE
пока единственное что у меня получается с тем функционалом который мне нужен - это перенос всего условного кода внутрь объекта в h файле, тогда все нормально работает.
Ваш вариант пока не пробовал, может и взлетит, но у меня задача вырезать не отдельный оператор а весь класс целиком... Конечно не очень красиво...
пока остановился на таком варианте, условие на 26 строке
#ifndef A_HOUSE_ADDON_H #define A_HOUSE_ADDON_H #include #include // ------------------------------------------------------------ // Описания использемых типов данных и зон где они получены/действуют #define TYPE_UNDEFINED 0 // неопределено #define TYPE_DATE_TIME 1 // Тип данных - дата и время, 7 байт #define TYPE_TERM 2 // Тип данных температура, 2 байта #define ZONE_UNDEFINED 0 // неопределено #define ZONE_ALL 1 // везде #define ZONE_OUTD0OR 2 // на улице // ------------------------------------------------------------ // ------------------------------------------------------------ // Описания функций используемых в объектах и в проекте unsigned long getDelayTime(unsigned long start_time, unsigned long end_time); // ------------------------------------------------------------ #ifdef DATE_TIME_USE const uint8_t daysInMonth [12] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 }; class addon_DateTime { private: long time_to_long(uint16_t Y, uint8_t M, uint8_t D, uint8_t h, uint8_t m, uint8_t s) // количество секунд после 2000/01/01, действительно для периода 2001..2099 // ********************************************************* { if (Y >= 2000) Y -= 2000; uint16_t days = D; for (uint8_t i = 1; i < M; ++i) days += pgm_read_byte(daysInMonth + i - 1); if (M > 2 && Y % 4 == 0) ++days; days = days + 365 * Y + (Y + 3) / 4 - 1; return ((days * 24L + h) * 60 + m) * 60 + s; } // ********************************************************* public: uint16_t year() { return 2000 + yOff; } uint8_t month() { return m; } uint8_t day() { return d; } uint8_t hour() { return hh; } uint8_t minute() { return mm; } uint8_t second() { return ss; } void SetDateTime () // ******************************************************** { long lt2 = offset + (millis() / 1000); if (lt > lt2) { // видимо был переход через 0 счетчика millis() offset = offset + 4294967; // это примерно 47 дней, что равно времени переполнения счетчика millis() lt = offset + (millis() / 1000); } else { lt = lt2; } lt2 = lt; ss = lt2 % 60; lt2 /= 60; mm = lt2 % 60; lt2 /= 60; hh = lt2 % 24; uint16_t days = lt2 / 24; uint8_t leap; for (yOff = 0; ; ++yOff) { leap = yOff % 4 == 0; if (days < 365 + leap) break; days -= 365 + leap; } for (m = 1; ; ++m) { uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1); if (leap && m == 2) ++daysPerMonth; if (days < daysPerMonth) break; days -= daysPerMonth; } d = days + 1; */ } // ******************************************************** void SetDateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec) // ******************************************************** { if (year >= 2000) year -= 2000; yOff = year; m = month; d = day; hh = hour; mm = min; ss = sec; lt = time_to_long(yOff, m, d, hh, mm, ss); offset = lt - (millis() / 1000); } // ********************************************************* void poll(unsigned long time_loop) // ********************************************************* { long a = time_loop / 1000; if ((lt - offset) != a) { SetDateTime(); } } // ********************************************************* protected: uint8_t yOff, m, d, hh, mm, ss; // хранит дату/время long lt; // хранит дату/время в секундах после 2000/01/01 long offset; // хранит количество секунд после 2000/01/01 на время последнего обнуления счетчика millis() }; #endif #endifну я почти так и делал, вся разница в том, что у Вас в cpp под директиву убраны 2 строки внутри процедуры а я убирал всю процедуру целиком, и компилятор банально выдавал ошибку вне зависимости от наличия DATE_TIME_USE
Значит, неправильно делали. Переписать вам мой пример с обрамлением всей процедуры?
1. Файл A_Config.h:
2. Файл Some.h:
#ifndef _SOME_H #define _SOME_H #include "A_Config.h" class Test { public: Test(); #ifdef DATE_TIME_USE void out(); #endif }; #endif3. Файл Some.cpp:
#include "Some.h" Test::Test() { } #ifdef DATE_TIME_USE void Test::out() { Serial.begin(9600); Serial.println("It's alive!"); } #endif4. Файл *.ino проекта:
расечатать?
#include "Some.h" void setup() { Test test; #ifdef DATE_TIME_USE test.out(); #endif }Ваш вариант пока не пробовал, может и взлетит, но у меня задача вырезать не отдельный оператор а весь класс целиком... Конечно не очень красиво...
Что значит "может и взлетит"? Куда оно денется - это же препроцессор, если понимать, как его использовать и почитать документацию - практически никаких ограничений, надо только грамотно юзать. Можно и весь класс убрать из компиляции, не вопрос. Проблем не вижу вообще, вернее, вижу одну проблему с вашей стороны - непонимание того, как работает препроцессор. Чуть-чуть разберётесь - и всё получится ;)
sketch\a_house.ino.cpp.o: In function `loop':
D:\arduino\mu_progect_169\a_house/a_house.ino:199: undefined reference to `addon_DateTime::poll(unsigned long)'
collect2.exe: error: ld returned 1 exit status
exit status 1
Ошибка компиляции для платы Arduino Nano.
Правильно, осталось только поправить эту ошибку, и всё. Вы вызываете функцию, которая была исключена директивами препроцессора. Если обрамить вызов этой фунции теми же директивами препроцессора, то вызов этой функции не попадёт в результирующий код.
Вы мой пример-то пробовали, или сразу кинулись готовый проект портить? Без понимания, как работают директивы препроцессора - не взлететь.