Официальный сайт компании Arduino по адресу arduino.cc
Видимость переменных
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Господа, добрый день! Просьба помочь новичку на этом форуме. Я не совсем новичок в программировании и ардуине, но помощь, все-таки, нужна.
Итак проблема. Код скетча получается очень сложный и громоздкий, поэтому решил его разбить на несколько файловых модулей (по функциональности). Хочу в этих файлах объявлять глобальные переменные, чтобы не выносить их в основной скетч (они тоже деляться по функциональности). Готов пользоваться определением extern, но при такой конфигурации (см. ниже) компановщик выдает ошибку "undefined reference".
Какие способы заставить видеть переменные, определенные модулем A.h в модуле B.h?
main.ino
#include "A.h" #include "B.h" void setup() { Serial.begin(9600); delay(200); InitTestVar(); //Присваивание 0 в модуле A.h SetTestVar(); //попытка присваивания 2 в модуле B.h Serial.print("nTest = "); //Вывод значения в Serial Serial.println(nTest); } void loop() { }
A.h
#ifndef _A_h #define _A_h #include <Arduino.h> byte nTest; //Объявление переменной в модуле A.h void InitTestVar(); //Объявление функции, присваивающей 0 переменной #endif
B.h
#ifndef _B_h #define _B_h #include <Arduino.h> extern byte nTest; //Указание на то, что переменная объявлена в другом месте void SetTestVar(); //Объявление функции, присваивающей переменной значение 2 #endif
Небольшая ремарка. Включение строки #include "A.h" в тело файла "B.h" приводит к ошибке "множественного определения переменной".
Прошу помощи. Заранее спасибо.
Переменные в .h файлах объявлять не нужно, их нужно объявлять в .ino .cpp файлах.
Заголовочные файлы нужны для других целей, например, чтобы сказать, что где то есть такая то переменная (extern), или функция, или класс, или черт с рогами.
Ну компилятор позволяет. К тому же, заголовочный файл удобен тем, что, по сути, определяет (описывает) интерфейс библиотеки/модуля по отношению к остальным участникам процесса и не нужно смотреть в cpp-файлы.
Но если по существу, то перенос объявлений в .сpp этого модуля эффекта не дает (естесственно). Я их в сообщении не указывал, поскольку, как мне кажется, они для описания проблемы не нужны. Вынос объявлений в .ino, по сути, является объявлением переменной в основном файле, чего я хочу избежать.
а чем это не устраивает? IDE само разобьет вкладки на файлы и проследит за корректностью их подключения.
в *.h-файле:
в *.cpp-файле:
Всё, теперь переменная Test доступна везде, где подключен соответствующий *.h-файл.
Ув. Целестрон. Прочтите свой текст, как компилятор. То есть заменив инклюды на полный текст включаемого. Вы получите в одном тексте ДВА объявления переменной, в extern и без него.
Файл программы, вместе с включаемыми файлами должен содержать лишь одно объявление переменной.
Другие файлы - в другой вкладке, для среды Ардуино важно, что открытой на момент компиляции. В среде нет понятия «проект», по крайней мере пока нет.
В среде важно, что типы файлов бывают только .ino. Среда подключит любой, но компилировать не станет.
Итого имеем:
В скетче, или во включаемом директивой #include файле делаем описание extern. В другом файле, открытом на момент компиляции в другой вкладке среды, делаем нормальное объявление переменной. И этот другой может быть ТОЛЬКО *.ino.
Или пользуйтесь средством создания библиотек. Оно описано даже на русском.
Вот такие ограничения у среды. Она вообще для небольших проектов. Для больших — АтмелСтудия. Она тоже официально бесплатная. Можно даже любимый wiring подключить ;). И работать почти как в среде.
Коллеги, СПАСИБО огромное и за наводку и за подробное описание, что разъяснило мне принцип!
Все заработало как хочется.
Уважаю!!! :)
PS: работаю не в Атмеле, а в Visual Studio 2015 (+ VisualMicro)
Ув. Целестрон. Прочтите свой текст, как компилятор. То есть заменив инклюды на полный текст включаемого. Вы получите в одном тексте ДВА объявления переменной, в extern и без него.
Файл программы, вместе с включаемыми файлами должен содержать лишь одно объявление переменной.
Другие файлы - в другой вкладке, для среды Ардуино важно, что открытой на момент компиляции. В среде нет понятия «проект», по крайней мере пока нет.
В среде важно, что типы файлов бывают только .ino. Среда подключит любой, но компилировать не станет.
Итого имеем:
В скетче, или во включаемом директивой #include файле делаем описание extern. В другом файле, открытом на момент компиляции в другой вкладке среды, делаем нормальное объявление переменной. И этот другой может быть ТОЛЬКО *.ino.
Или пользуйтесь средством создания библиотек. Оно описано даже на русском.
Вот такие ограничения у среды. Она вообще для небольших проектов. Для больших — АтмелСтудия. Она тоже официально бесплатная. Можно даже любимый wiring подключить ;). И работать почти как в среде.
Кто сказал, что среда не будет компилировать .cpp файлы, которые расположены в том же каталоге, что и основной ino файл?
Доказательства, пожалуйста, иначе выглядит как бред
В среде важно, что типы файлов бывают только .ino. Среда подключит любой, но компилировать не станет.
Итого имеем:
В скетче, или во включаемом директивой #include файле делаем описание extern. В другом файле, открытом на момент компиляции в другой вкладке среды, делаем нормальное объявление переменной. И этот другой может быть ТОЛЬКО *.ino.
Или пользуйтесь средством создания библиотек. Оно описано даже на русском.
Вот такие ограничения у среды. Она вообще для небольших проектов. Для больших — АтмелСтудия. Она тоже официально бесплатная. Можно даже любимый wiring подключить ;). И работать почти как в среде.
Полный бред. У меня проект, в котором, наверное, штук 30 *.cpp-файлов, помимо, собственно, единственного *.ino - чой-то компилит их, даже не давится. Причём файлы не оформлены как библиотеки - тупо валяются рядом с *.ino.
В общем, прежде чем писать информацию, не соответствующую действительности - надо самому разобраться, что именно делает Arduino IDE, чтобы собрать проект. Не поверите - передаёт всё это добро gcc, чуть-чуть повозившись для начала. Что такое gcc? Правильно - компилятор с с/с++, со всеми вытекающими. И никаких ограничений на "только *.ino" - не существует.
В том же каталоге - будет, но среда просто сама откроет их при открытии скетча и вопрос не будет стоять.
Я не точно выразился, прошу прощения.
Будет компилировать из каталога проекта *.cpp и *.h, причем перед этим сделает то самое " чуть-чуть повозившись для начала" (я этот термин скопипащу, шоб не матерится по этому поводу;) а вот *.inc пока не тыкнеш явно не включит в сборку, и главный бонус - не будет этого " чуть-чуть повозившись для начала", потому я строки кирилицы токо так и цепляю. Про Visual Studio 2015 & GCC - оба авторитетные, заслуженые и неизвестно ещё кто из них профессиональней, потому приучившись жить с " чуть-чуть повозившись для начала" вполне нормально. Ну есть конечно моменты, но они есть свои и в Visual Studio. По теме ТС - учите С/С++ и области видимости в ардуино станут подзрительно напоминать изученное.
В чем смысл использовать неизвестные среде расширения? Мне просто хочется понять логику, а то звучит, типа "я хочу так, а он не понимает". Объясните, пожалуйста.
В чем смысл использовать неизвестные среде расширения? Мне просто хочется понять логику, а то звучит, типа "я хочу так, а он не понимает". Объясните, пожалуйста.
Неужели непонятно?! Избегаем извратов препроцессора ардуины вообще и перекодировки кирилицы в частност. Количество тем о этой проблеме на форуме - десятки.
Ну не всем интересны проблемы с кодировками.
Для больших — АтмелСтудия. Она тоже официально бесплатная. Можно даже любимый wiring подключить ;). И работать почти как в среде.
подробнее можно, пожалуйста. Какая версия ? Атмел студио или AVR Studio разница есть? Как Вринг прикрутить?
PS: работаю не в Атмеле, а в Visual Studio 2015 (+ VisualMicro)
подробнее можно?
подробнее можно, пожалуйста. Какая версия ? Атмел студио или AVR Studio разница есть? Как Вринг прикрутить?
AVRStudio теперь называется AtmelStudio и с какой-то там версии, (в 7 уж точно) поддерживает Ардуино.
А wiring это просто библиотека с открытым исходным кодом, никто не мешает Вам включить ее в проект на AtmelStudio.
В 7ую версию, вроде как и включать ничего не нужно, там сразу есть поддержка скетчей, а следовательно и полной версии wiring. То есть именно скетчей, с setup() и loop(). Но сам я пока не пробовал. все руки не доходили.
Вдруг кто-то будет читать после меня... ;) Не увидел прямого ответа, поэтому вот.
...компановщик выдает ошибку "undefined reference".
Мне кажется, компоновщик пишет "_неопределенная_ ссылка".
Ни в одном из файлов nTest не определено, т.е. ему ничего не присвоено.
Сделайте в main.cpp nTest = 33, например - и все должно заработать.
Сделайте в main.cpp nTest = 33, например - и все должно заработать.
почему оно должно заработать? Инициализация переменной не имеет никакого отношения к этой ошибке
Как правильно исправить эту ошибку подробно описанов в ветке, не надо ничего придумывать
Как правильно исправить эту ошибку подробно описанов в ветке, не надо ничего придумывать
+100500
И некропосты с "решениями" вообще моветон. Ладно бы если возник вопрос, но пытаться ответить на вопрос через три года это просто издевательство :)