Написание библиотек, использующих библиотеки, которые используются в скетче
Я знаю, что название немного тупое, но позвольте мне попытаться объяснить: Я пытаюсь создать библиотеку простых функций для использования с моей TFT-панелью.
В панели есть включаемый файл (#include "SSD1306Wire.h"
)
У меня есть эскиз, и в эскизе есть ссылка на указанный выше файл #include
Я также хочу использовать свою библиотеку tftHelper.h
, но эта библиотека также должна ссылаться на SSD1306Wire.h
, чтобы вспомогательные функции работали.
Есть ли способ сослаться на SSD1306Wire.h
один раз и иметь возможность использовать ссылку в функциях моей вспомогательной библиотеки?
Я думаю, что еще важнее, как правильно поступить в такой ситуации?
@Timothy Girard, 👍3
2 ответа
Правильный способ справиться с этим — добавить #include guard в заголовочный файл, чтобы предотвратить включение содержимого более одного раза.
В заголовочном файле filename.h
вы должны добавить что-то вроде этого:
#ifndef _FILENAME_H_
#define _FILENAME_H_
// Здесь ваш код заголовка
#endif /* _FILENAME_H_ */
Блок #ifndef
не позволит коду быть включенным более одного раза. Лучше всего всегда помещать защитные элементы включения в заголовочные файлы.
Библиотека не имеет возможности узнать, что находится в вашем эскизе. Эти две вещи полностью разделены, и нет способа преодолеть этот разрыв.
Вы не можете включить библиотеку A в эскиз и ожидать, что библиотека B узнает об этом. Библиотека B должна явно включать в себя библиотеку A, чтобы библиотека B вообще имела представление о том, что такое библиотека A.
Включение библиотеки состоит из двух важных частей. Оно не только сообщает единице перевода, что вы включаете ее в то, что есть в библиотеке, но и сообщает IDE, что вы хотите использовать эту библиотеку и скомпилировать для нее исходный код.
Видите ли, библиотека обычно содержит две отдельные вещи — заголовочный файл (или несколько заголовочных файлов) и файлы исходного кода. Заголовочный файл описывает библиотеку — какие классы она имеет, какие экспортированные функции или переменные и т. д. Исходный код реализует библиотеку. Когда вы включаете библиотеку, он просто вставляет это определение библиотеки (заголовочный файл) в ваш исходный код в точке #include
. Так же, как копировать-вставить.
IDE делает немного дополнительной магии и связывает этот файл заголовка с каталогом, в котором есть другие файлы. Затем он находит файлы исходного кода в этом месте и компилирует их.
Каждый компилируемый файл компилируется отдельно. Это называется единицей перевода (TU), и каждая из них полностью отделена от всех остальных. Никто не может знать, что есть в любом другом файле, если только вы явно не скажете этому файлу найти что-то где-то еще (хотя вы не скажете ему где, а только то, что это «существует где-то еще»). И именно это делают заголовочные файлы — они сообщают единицам перевода, какие вещи доступны в другом месте.
Так что если TU A нужен ресурс F, ему нужно об этом сказать. Если TU B нужен ресурс F, ему тоже нужно об этом сказать.
И из-за дополнительных возможностей IDE ваш основной эскиз также должен быть проинформирован о каждой используемой библиотеке — независимо от того, используется ли эта библиотека напрямую эскизом или нет — чтобы он знал, что нужно найти и скомпилировать исходный код для этой библиотеки.
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату