Видимость #define

Тема в разделе "Arduino & Shields", создана пользователем sslobodyan, 12 фев 2017.

Метки:
  1. sslobodyan

    sslobodyan Гик

    Всем привет.
    Объясните мне какая зона видимости у #define. Если делать объявление в h файле, то компилятор его видит. А если подключать библиотеку либо внешний модуль, то не видит. Я раньше думал, что объявленный дефайн в основном h файле будет видимым во всех подключаемых. Нет, не видимый. Неужели невозможно делать определение на самом верхнем уровне, что бы подключаемые файлы его видели?
     
  2. CryNET

    CryNET Гик

    Если не ошибаюсь, то в подключаемой .h надо прописывать тот header, в котором задан ваш #define.
    //С одной стороны это удобно для избежания конфликтов, т.к. бывают проекты с "сотнями" header'ов. Можете отдельно сделать "global.h" и туда прописать что вам надо и потом сделать include в нужные либы. Возможно я ошибаюсь...
     
  3. rkit

    rkit Гуру

    Я думаю, что у вас проблема с порядком #include
    #define виден во всех строчках, что ниже определения
    #include просто подставляет текст включаемого файла вместо этой строчки.
    Соотвественно, .h с #define должен включаться перед .h, его использующим.
     
    CryNET нравится это.
  4. mcureenab

    mcureenab Гуру

    Макросы видны препроцессору от точки определения до конца единицы компиляции, включая h файлы ниже по тексту. После фазы препроцессора компилятор получает целый файл в который включены все h файлы и все макросы заменены на их содержимое.

    Библиотеки обычно сопровождаются заголовочным файлом с определениями. Если не сложно, дайте пример. Что ожидали увидеть, и что получилось по факту.
     
  5. CryNET

    CryNET Гик

    Я думаю, что rkit и mcureenab истину глаголят, в самый верх над includ'ом пишите и получится.
     
  6. Unixon

    Unixon Оракул Модератор

    Порядок #include не всегда спасает, в т.ч. поэтому глобальные макросы определяются через опции компилятора. Например, если одинаковый исходник нужно немного по-разному собрать или модули не должны ничего друг о друге знать, но у них есть условные директивы на одни и те же макросы.
     
  7. sslobodyan

    sslobodyan Гик

    Смотрите пример и поправьте меня, в чем не прав.
    Главный файл с подгрузкой библиотек:
    Код (C++):
    #define TEST_DEFINE
    #include <EEPROM.h>
    #include <SPI.h>
    #include "NRF24.h"
    Как видите, вначале я сделал определение.
    Теперь кусок реализации библиотеки NRF24.cpp:
    Код (C++):
    #ifdef TEST_DEFINE
      #error Test define passed!
    #else
      #error Error define!
    #endif
     
    Так вот у меня всегда останавливается компиляция на Error define!, хотя я ж вроде сделал определение ДО подключения библиотек.
     
  8. rkit

    rkit Гуру

    Вы включили NRF24.h, а #ifdef у вас в NRF24.cpp
    Это разные файлы.
     
  9. sslobodyan

    sslobodyan Гик

    Это понятно что разные, но почему срр подключается раньше? Я считал, что мы в инклуде пишем хедэр, а уже хедэр подключает реализацию срр. Так как мне правильно сделать, чтобы определение в главном файле (или главном хедэре) было видно в подключаемых? Дайте примерчик.
    Даже уточню вопрос.
    Вот, к примеру, в библиотеке SerialHardware есть определение размерности входящего и исходящего буфера
    Код (C++):
    #if !defined(SERIAL_TX_BUFFER_SIZE)
    #define SERIAL_TX_BUFFER_SIZE 16
     
    Как я могу самостоятельно определить этот SERIAL_TX_BUFFER_SIZE ?
     
    Последнее редактирование: 13 фев 2017
  10. rkit

    rkit Гуру

    cpp не подключается. Все cpp-файлы компилируются раздельно и независимо, а после этого линкуются в уже выходной бинарник.
    Глобальные переменные обычно пишут в make и configure-скриптах, но среда ардино все это не поддерживает.
    Самое простое - завести settings.h, и импортировать его из каждого файла.
     
    sslobodyan нравится это.
  11. mcureenab

    mcureenab Гуру

    NRF24.cpp не подключается в исходник скетча. Он компилируется отдельно в свой объектный файл а затем линковщик собирает объектные файлы в загружаемый hex. Так что ваш

    Код (C++):
    #define TEST_DEFINE
    он не видит.
     
  12. mcureenab

    mcureenab Гуру

    Грязными руками влезть в исходник библиотеки и поправить как вам надо. )))

    В полноценных IDE это делается на уровне настроек проекта. Затем make видит, что проект поменялся и заново собирает объектные файлы с новыми макросами и т.д.. А в Arduino IDE это недоступно.
     
  13. sslobodyan

    sslobodyan Гик

    Та я так и делаю, но искал более красивый метод :(
    Не понятно, зачем тогда в библиотеках делают проверку определений, если извне их не поправишь.
    В принципе то я понял, что в этой оболочке все плохо. Был лучик надежды, что это я просто чего то не знаю.
     
  14. mcureenab

    mcureenab Гуру

    Библиотеки изначально могли предназначаться для взрослых IDE. Их скопипастили и используют для Arduino.
     
  15. sslobodyan

    sslobodyan Гик

    Почитал как компилирует ардуина. Жесть. Получается, что если я в одном проекте использую сериальный буфер на 64 байта, то в другом проекте с этой же стандартной библиотекой мне придется помнить, что размер буфера я поменял с 256 на 64. И никак не выкрутится? А если через полгода забыл, то все, куча ошибок на этапе выполнения и неделя разбирательств почему устройство раньше работало.
     
  16. rkit

    rkit Гуру

    Ардуино это платформа для быстрого прототипирования, и все оптимизировано под эти цели. Нужны сложные проекты с переписыванием ядра, и прочим - используйте другие ИДЕ.
     
    sslobodyan нравится это.
  17. mcureenab

    mcureenab Гуру

    смотрим
    https://github.com/akupila/NRF24/blob/master/NRF24.h
    видим
    Код (C++):
    #include <Arduino.h>
    А Arduino.h включает
    pins_arduino.h

    а последний в свою очередь выбирается из каталога variants в зависимости от выбраной платы.
    Дескриптор платы лежит в файле

    https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/boards.txt

    Вы можете описать свою плату и настраивать её include файлы как надо, не трогая библиотеки.

    Вот как то так.

    Еще стоит посмотреть ядра для ATtiny. Там минимальный набор файлов ядра инструкция по подключению в IDE.
     
    Neilon, arkadyf и sslobodyan нравится это.
  18. sslobodyan

    sslobodyan Гик

    Я это знаю, скажите как поступать с двумя разными проектами на одной и той же плате? Которые требуют разную размерность буфера?
     
  19. mcureenab

    mcureenab Гуру

    Разные платы создать или варианты одной платы. Так сразу не скажу. Поковырять надо. Может быть Arduino IDE экспортирует переменную окружения с путем к скетчу... или в опциях компилятора прицепить файл определений.
     
    arkadyf нравится это.
  20. Unixon

    Unixon Оракул Модератор

    Форкнуть IDE на Github, добавить настройки в интерфейс, собрать для себя, отправить pull request, добиться включения в upstream, дождаться выхода нового выпуска.
     
    sslobodyan нравится это.