Как IDE организует вещи
Во-первых, вот как 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 ++ для всех намерений и целей. Однако создание прототипа функции может привести к неясным сообщениям об ошибках, если вы не будете осторожны.
Избежание причуд препроцессора
Самый простой способ избежать этих идиосинкразий - оставить основной эскиз пустым (и не использовать другие .ino
файлы). Затем создайте еще одну вкладку ( .cpp
файл) и поместите в нее свои вещи так:
#include <Arduino.h>
// put your sketch here ...
void setup ()
{
} // end of setup
void loop ()
{
} // end of loop
Обратите внимание, что вам нужно включить Arduino.h
. Среда IDE делает это автоматически для основного эскиза, но для других модулей компиляции это необходимо сделать. В противном случае он не будет знать о таких вещах, как String, аппаратные регистры и т. Д.
Как избежать установки / основной парадигмы
Вам не нужно работать с концепцией настройки / цикла. Например, ваш файл .cpp может быть:
#include <Arduino.h>
int main ()
{
init (); // initialize timers
Serial.begin (115200);
Serial.println ("Hello, world");
Serial.flush (); // let serial printing finish
} // end of main
Принудительное включение библиотеки
Если вы работаете с концепцией «пустой эскиз», вам все равно нужно включить библиотеки, используемые в других местах проекта, например, в ваш основной .ino
файл:
#include <Wire.h>
#include <SPI.h>
#include <EEPROM.h>
Это связано с тем, что среда IDE сканирует только основной файл на предмет использования библиотеки. По сути, вы можете рассматривать основной файл как файл проекта, который указывает, какие внешние библиотеки используются.
Проблемы с именами
Не называйте ваш главный набросок "main.cpp" - в среде IDE есть собственный main.cpp, поэтому у вас будет дубликат, если вы это сделаете.
Не называйте ваш .cpp файл тем же именем, что и ваш основной .ino файл. Поскольку файл .ino фактически превращается в файл .cpp, это также даст вам конфликт имен.
Объявление класса в стиле C ++ в одном и том же файле .ino (слышал, но никогда не видел работающим - это вообще возможно?);
Да, это компилируется нормально:
class foo {
public:
};
foo bar;
void setup () { }
void loop () { }
Однако вам, вероятно, лучше всего следовать обычной практике: поместите ваши декларации в .h
файлы, а ваши определения (реализации) в .cpp
(или .c
) файлы.
Почему "наверное"?
Как показывает мой пример, вы можете собрать все в один файл. Для более крупных проектов лучше быть более организованным. В конце концов вы попадаете на сцену в средне-крупномасштабном проекте, где вы хотите разделить вещи на «черные ящики», то есть класс, который делает одно, делает это хорошо, тестируется и самодостаточен ( настолько далеко, насколько возможно).
Если этот класс затем используется в нескольких других файлах в вашем проекте, то здесь отдельные .h
и .cpp
файлы вступают в игру.
.h
Файл объявляет класс - то есть, он обеспечивает достаточно деталей для других файлов , чтобы знать , что он делает, какие функции у него есть, и как они называются.
В .cpp
файл определяет (реализует) класс - то есть, он на самом деле обеспечивает функции и статические члены класса, которые делают класс делать свое дело. Поскольку вы хотите реализовать его только один раз, это находится в отдельном файле.
.h
Файл , что входит в другие файлы. .cpp
Файл компилируется один раз в IDE для реализации функций класса.
Библиотеки
Если вы следуете этой парадигме, то вы готовы очень легко переместить весь класс ( файлы .h
и .cpp
файлы) в библиотеку. Затем его можно разделить между несколькими проектами. Все , что требуется , чтобы сделать папку (например. myLibrary
) И поставить .h
и .cpp
файлы в ней (например, myLibrary.h
а myLibrary.cpp
) , а затем поместить эту папку внутри libraries
папки в папку , в которой хранятся ваши эскизы (этюдник папку).
Перезапустите IDE, и теперь она знает об этой библиотеке. Это действительно тривиально просто, и теперь вы можете поделиться этой библиотекой с несколькими проектами. Я делаю это много.
Чуть подробнее здесь .