использование буфера для символов - что не так програмирую?
- Войдите на сайт для отправки комментариев
Ср, 14/08/2013 - 05:10
потратил несколько часов разбирая глюк. Пишу под мегу и столкнулся вот с чем.
У меня скетч разбит на несколько файлов, в одном есть такое:
char sdlog_buf[100]; inline char* sdlogBuf() { return sdlog_buf; }
в другом:
static void utft_statusIP(uint32_t ip) { char buf[20]; uint8_t *bytes = (uint8_t*)&ip; myGLCD.setBackColor(0, 255, 0); myGLCD.setColor(0, 0, 0); sprintf(sdlogBuf(), "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]); myGLCD.print(sdlogBuf(), UTFT_STATUS_XMIN, UTFT_STATUS_YMIN); myGLCD.setBackColor(0, 0, 0); }
так вот если откомментировать строку с myGLCD.print то ри попытке прошить скетч начинают сыпаться ошибки averdude, а если ее закомментировать - нет проблем. Так же не будет проблем если буфер объявить внутри файла и обращаться к нему напрямую. Мне показалось лучше иметь один большой буфер чем много раз их объявлять - это жкономит ресурсы и не требует динамического выделения. Не понимаю в чем подстава, вроде обращение в массиву через функуцию ничем не отличается
А зачем тут вообще функция? Почему sdlog_buf напрямую не использовать?
Чем
не устраивает?
А зачем тут вообще функция? Почему sdlog_buf напрямую не использовать?
Чем
не устраивает?
скетч большой, разделен на "закладки" т.е. много файлов. переменная объявленная в одном файле не видна в других.
Чудно. Что-то вы не договариваете. Функция значит видна, а переменная нет? Как так? Или функция тоже не видна и проблема в этом? Может и ошибки сыпятся на из avrdude? (ему-то что? он вообще взял бинарник и послал его... в его суть - он не вникает).
Это раз. Во вторых, может направится в сторону того что-бы "переменная стала видна"?
Но тут вам помочь, пока - не представляется возможности. Вы, как частенько тут делают, упустили детали не важные с вашей точки зрения, а ведь именно они и могут быть "ответом".
А именно что значит "разбита на закладки?". То есть "понятно", но ведь тоже много вариантов. Смотря на кикие именно файлы. На .ino, на .cpp, на .h . Они хоть и выглядят во вкладках "похоже", но ведь компилируются/линкуются весьма по разному (и скажем честно, у ардуины иногда - действительно бывают "магические заглюки" в процессе этого).
Исходя из того "что же там у вас творится", можно разные направления решения копать:
1. Вынести вашу переменную в отдельный .h и инклудить его туда где она требуется (это как-бы сишный путь)
2. Пихать ее в повыше в главный скетч. Следить за тем в каком порядке ArduinoIDE объединяет .ino файлы (если не ошибаюсь - тупо в алфавитном)
3. Воспользоваться ключевым словом extern (пообещать компилятору/линкеру, что "где-то в других файлах" у нас будет объявлена эта переменная).
Вообщем вариант (2) - я не люблю. Привязывать компилируемость програмы к именам файла - бу-э. Как и засорять главный скетч.
Вообщем попрбуйте такие варианты:
Вариант (1):
Создаем в папке файл с именем CommonVars.h
В него
Заодно и размеру буфера дали имя. Пригодится если где-то в коде нужно будет проверять (а не превысили-ли мы ...)
Ну а потом, везеде где вам потребовался буффер делаете
и пользуетесь свои буфером.
Вариант 3:
Вверху второго файла (который с myGLCD) пишите:
-----
Если у вас таких "общих переменных" всегод одна. Вариант (3) будет, наверное проще. Но это "костыль". Если же вы планируете и дальше использовать что-то общее (переменные, константы, типы), тогда Вариант 2 однозначно. Подключил один файлик - и у тебя все есть :)
Чудно. Что-то вы не договариваете. Функция значит видна, а переменная нет? Как так?
если бы я знал ответ, я бы не спрашивал, именно! функция видна, а переменная нет)) что вы меня сразу во всех грехах обвиняете?) сам прекрасно знаю, что правильный ответ это на 80% правильно заданный вопрос. Ничего я не утаиваю - в начале темы указано про то, что проект разбит на файлы. Как раз если добавлять "закладку" (стрелочка вниз слева вверху окна редактирования) то вариант расширения файла будет один - .ino.
Или функция тоже не видна и проблема в этом? Может и ошибки сыпятся на из avrdude? (ему-то что? он вообще взял бинарник и послал его... в его суть - он не вникает).
самому странно) но факт 100%!!! проверял много раз. стоит разкоментировать строку где есть вызов функции как после этого я не могу залить скетч!
Исходя из того "что же там у вас творится", можно разные направления решения копать:
1. Вынести вашу переменную в отдельный .h и инклудить его туда где она требуется (это как-бы сишный путь)
2. Пихать ее в повыше в главный скетч. Следить за тем в каком порядке ArduinoIDE объединяет .ino файлы (если не ошибаюсь - тупо в алфавитном)
3. Воспользоваться ключевым словом extern (пообещать компилятору/линкеру, что "где-то в других файлах" у нас будет объявлена эта переменная).
пробовал все, если включать один и тот же файл в разные "закладки" позникает конфликт. Тоже происходит если использовать extern.
На самом деле вы наверно правы - ардуино "тупо" склеивает все файлы проекта в один в том порядке в котором они отображатся в окне редактиврования. Я вставил определение буфера в самый левый файл и она стала видна в других "закладках"
спасибо за подсказки
пробовал все, если включать один и тот же файл в разные "закладки" позникает конфликт. Тоже происходит если использовать extern.
Ну если вы "пробовали все" - то тогда "ничем не поможешь".
Но я бы, все-таки, рекомендовал попробовать вариант c .h файлом. Именно с таким именем и таким расширением как я написал. И не выкидывать из него ничего (особенно первый две и последнюю строку). Тогда никаких конфликтов от многократного включения - не должно быть.
Категорически не соглашусь с вариантом, когда в .h файле объявляются переменные. В таких файлах максимум можно описать внешние переменные со словом extern. Сами переменные нужно объявить в подходящем .cpp (ino) файле. Спорить не хочу и не вижу смысла.
Один из вариантов (leshak, я взял за основу твои исходники):
Файл foo.h:
Файл foo.ino:
Файл foo2.cpp:
.h файлы предназначены только для описания чего то, а не для объявления объектов, переменных и т.п.
Пример, что я привел - компилируется, я проверил.
Спорить не хочу и не вижу смысла.
"Не вижу смысла" - это слабый довод. Не видеть смысла - это может и означать ограниченность знаний. Не в данном случае, конечно, а "в общем". Я скорее против довода "спорить не хочу, так как смысла не вижу". Так и провоцирует поспорить :)
Хотя, в данном случае, спорить-то особо никто и не собирался :) . Я тоже стараюсь всегда связку h/cpp использовать (ну хотя бы потому, что потом легче в виде библиотеки оформить). Но... как "быстрое решение проблемы" переменная в .h - тоже работает. Проверенно :) Но, конечно, это "нарушение идиологического духа". Никто спорить не будет :) Ваш вариант - кошерней :)
А вот по поводу "#pragma once" - возможно стоило бы. Цитата из вики:
В языках программирования Си и C++ #pragma once — нестандартная, но широко распространенная препроцессорная директива, разработанная для контроля за тем, чтобы конкретный исходный файл при компиляции подключался строго один раз. То есть, #pragma once применяется для тех же целей, что и include guard, но требует меньше кода и не допускает возможности коллизии имён. Считается устаревшей и для применения не рекомендуется
К тому же "include guard" - я уже написал (хе-хе, не знал что эта конструкция имеет свое название). Так что две конструкции для одного и того же - явно избыточны. Тем более, что
С другой стороны, некоторые компиляторы, как например, GCC, также используют специальный код для распознавания и оптимизации обработки include guard.[1]
Так что "две конструкции сразу" имели бы смысл только если мы бы планировали этот код компилировать какими-то неведомыми компиляторами.
Ну если вы "пробовали все" - то тогда "ничем не поможешь".
так уже помогли)) переменную надо объявлять в файле самом левом
ардуино как я вижу собирает проект не как принято через компиляцию отдельных файлов и последующую их линковку - ардуино через препроцессор склеивает все файлы и компилирует проект как один большой склееный файл. Отсюда возникают нюансы - например зависимость от того в каком файле даешь определение.
leshak, спорить не вижу смысла, потому что опыт программирования у меня достаточный, он и подсказывает.
На счет pragma, просто привычка, потому что мне приходиться компилировать разными компиляторами одни и те же исходники. Поскольку и то и другое не противоречит, пишу и то и другое. Здесь, наверное, это излишество.
Я не хочу сказать что у вас нет опыта (при этом все равно есть шансы натолкнутся на новинку или неочевидный нюанс). Его наличие - очевидно из самой сути вашего замечания. Возможно даже поболее моего (все-таки C/C++ для меня "не родные", до ардуины я на них в школе один hello world написал :) и это было давно, уже с ардуиной пришлось вспоминать "как оно жить без GarbageCollector-а" :) . Тут скорее сам ваш речевой оборот, скажем так... задевает :) И вызывает прямо противоположную реакцию.
В частности - цепляние к pragma :) Хотя, конечно, изначально понимал что это "привычка". Возможно даже полезная :) Проще чуть-чуть избыточности безопастной в привычках иметь, чем каждый раз тратить такты мозга на решение "а что тут лучше выбрать". Так что - отлично вас понимаю.
А то что формально вы правы - так я сразу признал. Ну поленился я. Что я, не человек? ;)
как я вижу собирает проект не как принято через компиляцию отдельных файлов и последующую их линковку -
Еще как собирает. Вы файлам дайте расширение "как принято" .h/.cpp - будет вам линковка. А .ino - принято склеивать. Так что у вас полная свобода выбора "как вам проект собирать" :) Ну разве что, не помню, можно ли прямо из ArduinoIDE файлу расширение сменить. Но, в крайнем случае, мы и без ArduinoIDE файлы создавать умеем :)
Если сделать как в моем примере, то неважно, склейка будет или нет, ошибок компиляции не будет.