Видимость переменных

Celestron
Offline
Зарегистрирован: 13.04.2016

Господа, добрый день! Просьба помочь новичку на этом форуме. Я не совсем новичок в программировании и ардуине, но помощь, все-таки, нужна.

Итак проблема. Код скетча получается очень сложный и громоздкий, поэтому решил его разбить на несколько файловых модулей (по функциональности). Хочу в этих файлах объявлять глобальные переменные, чтобы не выносить их в основной скетч (они тоже деляться по функциональности). Готов пользоваться определением 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" приводит к ошибке "множественного определения переменной".

Прошу помощи. Заранее спасибо.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Переменные в .h файлах объявлять не нужно, их нужно объявлять в .ino .cpp файлах.
Заголовочные файлы нужны для других целей, например, чтобы сказать, что где то есть такая то переменная (extern), или функция, или класс, или черт с рогами.

Celestron
Offline
Зарегистрирован: 13.04.2016

Ну компилятор позволяет. К тому же, заголовочный файл удобен тем, что, по сути, определяет (описывает) интерфейс библиотеки/модуля по отношению к остальным участникам процесса и не нужно смотреть в cpp-файлы.

Но если по существу, то перенос объявлений в .сpp этого модуля эффекта не дает (естесственно).  Я их в сообщении не указывал, поскольку, как мне кажется, они для описания проблемы не нужны. Вынос объявлений в .ino, по сути, является объявлением переменной в основном файле, чего я хочу избежать.

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

а чем это не устраивает? IDE само разобьет вкладки на файлы и проследит за корректностью их подключения.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

в *.h-файле:

extern byte Test;

в *.cpp-файле:

byte Test = 0;

Всё, теперь переменная Test доступна везде, где подключен соответствующий *.h-файл.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Ув. Целестрон. Прочтите свой текст, как компилятор. То есть заменив инклюды на полный текст включаемого. Вы получите в одном тексте ДВА объявления переменной, в extern и без него.

Файл программы, вместе с включаемыми файлами должен содержать лишь одно объявление переменной.

Другие файлы - в другой вкладке, для среды Ардуино важно, что открытой на момент компиляции. В среде нет понятия «проект», по крайней мере пока нет.

В среде важно, что типы файлов бывают только .ino. Среда подключит любой, но компилировать не станет.

 

Итого имеем:

В скетче, или во включаемом директивой #include файле делаем описание extern. В другом файле, открытом на момент компиляции в другой вкладке среды, делаем нормальное объявление переменной. И этот другой может быть ТОЛЬКО *.ino.

Или пользуйтесь средством создания библиотек. Оно описано даже на русском.

 

Вот такие ограничения у среды. Она вообще для небольших проектов. Для больших — АтмелСтудия. Она тоже официально бесплатная. Можно даже любимый wiring подключить ;). И работать почти как в среде.

 

Celestron
Offline
Зарегистрирован: 13.04.2016

Коллеги, СПАСИБО огромное и за наводку и за подробное описание, что разъяснило мне принцип!

Все заработало как хочется.

Уважаю!!! :)

PS: работаю не в Атмеле, а в Visual Studio 2015 (+ VisualMicro)

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

wdrakula пишет:

Ув. Целестрон. Прочтите свой текст, как компилятор. То есть заменив инклюды на полный текст включаемого. Вы получите в одном тексте ДВА объявления переменной, в extern и без него.

Файл программы, вместе с включаемыми файлами должен содержать лишь одно объявление переменной.

Другие файлы - в другой вкладке, для среды Ардуино важно, что открытой на момент компиляции. В среде нет понятия «проект», по крайней мере пока нет.

В среде важно, что типы файлов бывают только .ino. Среда подключит любой, но компилировать не станет.

 

Итого имеем:

В скетче, или во включаемом директивой #include файле делаем описание extern. В другом файле, открытом на момент компиляции в другой вкладке среды, делаем нормальное объявление переменной. И этот другой может быть ТОЛЬКО *.ino.

Или пользуйтесь средством создания библиотек. Оно описано даже на русском.

 

Вот такие ограничения у среды. Она вообще для небольших проектов. Для больших — АтмелСтудия. Она тоже официально бесплатная. Можно даже любимый wiring подключить ;). И работать почти как в среде.

 


Кто сказал, что среда не будет компилировать .cpp файлы, которые расположены в том же каталоге, что и основной ino файл?
Доказательства, пожалуйста, иначе выглядит как бред

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

wdrakula пишет:

В среде важно, что типы файлов бывают только .ino. Среда подключит любой, но компилировать не станет.

 

Итого имеем:

В скетче, или во включаемом директивой #include файле делаем описание extern. В другом файле, открытом на момент компиляции в другой вкладке среды, делаем нормальное объявление переменной. И этот другой может быть ТОЛЬКО *.ino.

Или пользуйтесь средством создания библиотек. Оно описано даже на русском.

 

Вот такие ограничения у среды. Она вообще для небольших проектов. Для больших — АтмелСтудия. Она тоже официально бесплатная. Можно даже любимый wiring подключить ;). И работать почти как в среде.

Полный бред. У меня проект, в котором, наверное, штук 30 *.cpp-файлов, помимо, собственно, единственного *.ino - чой-то компилит их, даже не давится. Причём файлы не оформлены как библиотеки - тупо валяются рядом с *.ino.

В общем, прежде чем писать информацию, не соответствующую действительности - надо самому разобраться, что именно делает Arduino IDE, чтобы собрать проект. Не поверите - передаёт всё это добро gcc, чуть-чуть повозившись для начала. Что такое gcc? Правильно - компилятор с с/с++, со всеми вытекающими. И никаких ограничений на "только *.ino" - не существует.

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

kisoft пишет:
Кто сказал, что среда не будет компилировать .cpp файлы, которые расположены в том же каталоге, что и основной ino файл? Доказательства, пожалуйста, иначе выглядит как бред

В том же каталоге - будет, но  среда просто сама откроет их при открытии скетча и вопрос не будет стоять.

Я не точно выразился, прошу прощения.

Logik
Онлайн
Зарегистрирован: 05.08.2014

Будет компилировать из каталога проекта *.cpp  и *.h,  причем перед этим сделает то самое " чуть-чуть повозившись для начала" (я этот термин скопипащу, шоб не матерится по этому поводу;) а вот *.inc пока не тыкнеш явно не включит в сборку, и главный бонус - не будет этого  " чуть-чуть повозившись для начала", потому я строки кирилицы токо так и цепляю. Про Visual Studio 2015 & GCC - оба авторитетные, заслуженые и неизвестно ещё кто из них профессиональней,  потому приучившись жить с " чуть-чуть повозившись для начала" вполне нормально. Ну есть конечно моменты, но они есть свои и в  Visual Studio. По теме ТС - учите С/С++ и области видимости в ардуино станут подзрительно напоминать изученное.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

В чем смысл использовать неизвестные среде расширения? Мне просто хочется понять логику, а то звучит, типа "я хочу так, а он не понимает". Объясните, пожалуйста.

 

Logik
Онлайн
Зарегистрирован: 05.08.2014

kisoft пишет:

В чем смысл использовать неизвестные среде расширения? Мне просто хочется понять логику, а то звучит, типа "я хочу так, а он не понимает". Объясните, пожалуйста.

 

Неужели непонятно?! Избегаем извратов препроцессора ардуины вообще и перекодировки кирилицы в частност. Количество тем о этой проблеме на форуме - десятки.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Ну не всем интересны проблемы с кодировками.

MacSim
Offline
Зарегистрирован: 28.11.2012

wdrakula пишет:

 

 Для больших — АтмелСтудия. Она тоже официально бесплатная. Можно даже любимый wiring подключить ;). И работать почти как в среде.

 

подробнее можно, пожалуйста. Какая версия ? Атмел студио или AVR Studio разница есть? Как Вринг прикрутить?

MacSim
Offline
Зарегистрирован: 28.11.2012

Celestron пишет:

PS: работаю не в Атмеле, а в Visual Studio 2015 (+ VisualMicro)

подробнее можно?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

MacSim пишет:

подробнее можно, пожалуйста. Какая версия ? Атмел студио или AVR Studio разница есть? Как Вринг прикрутить?

AVRStudio теперь называется AtmelStudio и с какой-то там версии, (в 7 уж точно) поддерживает Ардуино.

А wiring это просто библиотека с открытым исходным кодом, никто не мешает Вам включить ее в проект на AtmelStudio.

В 7ую версию, вроде как и включать ничего не нужно, там сразу есть поддержка скетчей, а следовательно и полной версии wiring. То есть именно скетчей, с setup() и loop(). Но сам я пока не пробовал. все руки не доходили.

sten58
Offline
Зарегистрирован: 05.12.2017

Вдруг кто-то будет читать после меня... ;) Не увидел прямого ответа, поэтому вот.

Celestron пишет:

...компановщик выдает ошибку "undefined reference".

Мне кажется, компоновщик пишет "_неопределенная_ ссылка".

Ни в одном из файлов nTest не определено, т.е. ему ничего не присвоено. 

Сделайте в main.cpp nTest = 33, например - и все должно заработать.

b707
Онлайн
Зарегистрирован: 26.05.2017

sten58 пишет:

Сделайте в main.cpp nTest = 33, например - и все должно заработать.

почему оно должно заработать? Инициализация переменной не имеет никакого отношения к этой ошибке

Как правильно исправить эту ошибку подробно описанов в ветке, не надо ничего придумывать

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

b707 пишет:

Как правильно исправить эту ошибку подробно описанов в ветке, не надо ничего придумывать

+100500

И некропосты с "решениями" вообще моветон. Ладно бы если возник вопрос, но пытаться ответить на вопрос через три года это просто издевательство :)