Что именно делает препроцессор Arduino?
Arduino утверждает, что является «языком», а не просто «инфраструктурой приложений», и файлы Arduino имеют собственное расширение .ino. Язык, очевидно, C++, но не совсем. Насколько я понимаю, у Arduino есть какой-то специальный препроцессор, который преобразует файлы .ino в файлы C++ перед их компиляцией.
Мой вопрос: что точно делает этот препроцессор? В чем именно разница между «языком Arduino» и настоящим C++? В документации Arduino это, кажется, замалчивается.
В частности, со мной происходили странные вещи, когда я пытался определить свои собственные классы в своем скетче. Трудно понять, что я делаю не так, когда язык нигде не указан.
@user31708, 👍3
Обсуждение2 ответа
Лучший ответ:
По сути, он делает четыре вещи:
- Он добавляет
#include <Arduino.h>в начало вашего файла, что дает вам доступ ко всем классам, функциям и определенным переменным/макросам API. - Он объединяет все файлы INO в один монолитный файл (в том же порядке, что и вкладки в окне),
- Он сопоставляет записи
#includeс библиотеками и добавляет файлы из этих библиотек в список файлов для компиляции, и - Он сканирует ino-файлы в поисках функций и добавляет к ним прототипы в начало вашего файла.
Последнее может вызвать проблемы. Исторически сложилось так, что прототипы никогда не помещались в нужное место, и если вы когда-нибудь передали в функцию структуру, придуманную вами самим, она бы ужасно сломалась. Сегодня он работает лучше, но все еще не идеален на 100 %.
По сути, это означает, что вам не нужно придерживаться правила C/C++ «Вы должны определить это, прежде чем использовать». Что, конечно, делает программистов ленивыми.
и он объединяет все ino-файлы проекта в один файл, начиная с ino-файла с тем же именем, что и у папки проекта, а затем остальных ino-файлов в алфавитном порядке (это тот же порядок, что и вкладки в IDE), @Juraj
Ах да, это тоже., @Majenko
См. мой ответ: Как IDE организует вещи
Я не уверен, что ответы, содержащие только ссылки и относящиеся к ссылке Stack Exchange, приемлемы. Если это не так, вот первая часть ответа:
Вот как IDE организует ваш «скетч»:
- Основной файл
.inoимеет то же имя, что и папка, в которой он находится. Итак, дляfoobar.inoвfoobarпапка — основной файл foobar.ino. - Все остальные файлы
.inoв этой папке объединяются в алфавитном порядке в конце основного файла (независимо от того, где находится основной файл, в алфавитном порядке). - Этот объединенный файл становится файлом
.cpp(например,foobar.cpp) — он помещается во временную папку компиляции. - Препроцессор «услужливо» генерирует прототипы функций, которые он находит в этом файле.
- Основной файл сканируется на наличие директив
#include <libraryname>. Это заставляет IDE также копировать все соответствующие файлы из каждой (упомянутой) библиотеки во временную папку и генерировать инструкции для их компиляции. - Любые файлы
.c,.cppили.asmв папке скетча добавляются в процесс сборки как отдельные единицы компиляции (которые то есть они компилируются обычным способом в отдельные файлы) - Все файлы
.hтакже копируются во временную папку компиляции, поэтому на них можно ссылаться в файлах .c или .cpp. - Компилятор добавляет в процесс сборки стандартные файлы (например,
main.cpp) - Затем процесс сборки компилирует все указанные выше файлы в объектные файлы.
- Если фаза компиляции прошла успешно, они скомпонуются вместе со стандартными библиотеками AVR (например, предоставив вам
strcpyи т. д.)
Побочным эффектом всего этого является то, что вы можете считать основной скетч (файлы .ino) по сути написанным на C++. Однако генерация прототипа функции может привести к неясным сообщениям об ошибках, если вы не будете осторожны.
Спасибо! Откуда вы узнали всю эту информацию?, @user31708
Наблюдение за тем, какие файлы копируются во временный каталог, и просмотр команд, выполняемых при включенной «подробной» компиляции., @Nick Gammon
Где находятся временные файлы? Можете ли вы настроить Arduino IDE так, чтобы их можно было легко просматривать?, @NeilenMarais
Если вы включите «подробную компиляцию», вы сможете увидеть, где находятся временные файлы., @Nick Gammon
- Цикл While не прерывается
- как отправить аргумент объектам ESP8266WebServer в функции
- оператор if не работает с дробью, но работает с десятичным эквивалентом
- Как изменить переменную/скетч с помощью графического интерфейса
- Обновите атрибут класса с помощью attachInterrupt
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
- Какие накладные расходы и другие соображения существуют при использовании структуры по сравнению с классом?
- Что лучше использовать: #define или const int для констант?
Конвертер Arduino ino в cpp не затрагивает ваши файлы cpp и h. Он преобразует только файл ino в файл cpp, как описал Маженко в своем ответе., @Juraj
*Со мной происходили странные вещи* - можете ли вы привести пример?, @Nick Gammon
@NickGammon Это было давно, поэтому я не помню точное сообщение об ошибке. Но я подозреваю, что это было вызвано автоматически созданными прототипами. (т.е. функция принимает структуру или класс в качестве аргумента, а прототип вставляется перед объявлением этой структуры или класса), @user31708