Передача параметров в библиотечный статический класс.
- Войдите на сайт для отправки комментариев
Функции для работы с неким LCD экраном собираются в библиотеку. Обычно в ней описан класс. В начале программы мы создаем его экземпляр, передавая параметры в конструкторе : LCD lcd(pin1,pin2,pin3). Дальше работаем с экземпляром, через его методы, например lcd.print("Hello World");
Особенность МК-based устройств в том, что в 99.99% случаев у них один экран, один GPS, одна клавиатура и т.д. А памяти очень мало. Поэтому я сделал все классы в таких библиотеках полностью статическими и
не трачу память на экземпляры класса. Все параметры устройства хранятся в тоже статическом классе Settings, а не в членах lcd. В LCD определяются поля вида static const uint8_t dcPin = Settings::lcdDcPin и оперативная память не тратится. Такой периферии и параметров много и памяти экономится прилично.
Всё хорошо пока не нужно использовать эту библиотеку(библиотеки) в нескольких проектах. У них класс LCD у всех один, но он зависит от класса Settings, а он в каждом проекте свой.
Интересно как прописать такую зависимость в библиотечный статический класс от локального класса не потратив ни байта оперативки?
Пахнет тут наследованием и этим... как его, черт... полиморфизмом.
Очевидно, интерфейсом. Просто передавать указатель на конкретный класс Settings в библиотечный.
Пахнет тут наследованием и этим... как его, черт... полиморфизмом.
Им самым ;)
задача не тратить ни байта оперативки, экземпляры LCD и Settings не создаются, в них все члены и методы статические, всё 100% static
Соглашение по методам, другого варианта решения не завезут. Каждый конкретный Settings - имеет один и тот же набор методов, пусть они сто раз статическими будут.
Кстати сказать: можно просто namespace юзать, раз всё равно всё в статике. И проще будет, и писанины меньше.
Спасибо за ответ, расскажите пожалуйста по-подробнее что значит "Соглашение по методам"
p.s. namespace разумеется юзаю, и лямбды и scoped enumы и inline члены классов но это вообще из другой оперы и к этой теме отношения не имеет
не трачу память на экземпляры класса. Все параметры устройства хранятся в тоже статическом классе Settings, а не в членах lcd. Интересно как прописать такую зависимость в библиотечный статический класс от локального класса не потратив ни байта оперативки?
Еще нехватает номера пинов при каждом чихе из PROGMEM тянуть. Если уж совсем "не тратить ни байта оперативки" можете попробовать через extern организовать. Но думаю это уже излишняя экономия. Я в подобных ситуациях делаю базовый Setings от него наследую в каждый проект свой и передаю указатель на него в LCD. Причем номера пинов не даю. Даю методы обмена с экраном, типа отправить байт, блок данных, ресета и т.д.
PROGMEM конечно нафиг. Он еще больше оперативки экономит.
Разумеется нафиг, PROGMEM это ближе к делу чем namespace, но если я в LCD описываю поле так
class Lcd {
...
static const uint8_t dcPin = Settings::nokia_dc;
}
а в Settings {
static const uint8_t nokia_dc = 7;
}
то в код будет подставляться именно константа, примерно как если-бы я пользовался define-ом, только с контролем типов и области видимости. Использовать PROGMEM тут не рационально т.к. придётся больше кода писать, больше флеша уйдёт на вызов pgm_read_xxx() и стека на вызов и на переменную в которую нужно читать из флеша.
Да, про extern тоже думал, но если я правильно понимаю возможности extern-а, extern-ом я могу объявить внешнюю переменную, но уже известного типа, например extern int x; а тип-то задаётся в локальном файле и мы вернулись к исходной проблеме.
У ДиХальта на форуме подсказали решение, в котором LCD - шаблонный класс, а Settings передается в него параметром, думаю, должно сработать.
Спасибо за ответ, расскажите пожалуйста по-подробнее что значит "Соглашение по методам"
Просто перечень методов, которые обязан реализовывать каждый конкретный Settings. Тогда LCD всегда будет знать, какие методы дёргать. Или я чего недопонял?
это библиотека - xlcd.h - лежит в ...arduino/libraries/
Ага, неплохо вроде.
Про extern - да, типы должны соответствовать , а в чем проблема то? Очевидно что параметро в Settings по типу должен соответствовать ожидаемому в LCD.
Проблема в том, что я описал в первом посте : LCD не может зависить от Settings т.к. в трех проектах Settings - у каждого свой. Разумеется, можно создать абстрактный ISettings и от него наследовать проектовые Settings и передавать их в конструкторе, но это мы вернулись к самому началу. LCD д.б. полностью статический класс.
Вариант с шаблонным классом, не тратящий оперативки я написал, он компилится и работает, любой может проверить. Если у вас получится сделать то-же, не тратя оперативки через extern - будет интересно посмотреть.
Ну как вариант это
/**/ typedef struct { /*создаем структуру набора настроек*/ byte a; byte b; byte c; } set_t ; enum set_e {set1 = 0, set2, set3}; /*создаем имена набора настроек*/ const set_t setting[] { {1, 2, 3}/*набор set1*/ , {1, 2, 3} /*набор set2*/ , {1, 2, 3} /*набор set3*/ }; class Cl_AAA { /*некий класс*/ byte a; byte b; byte c; public: void init(set_e i) { a = setting[i].a; b = setting[i].b; c = setting[i].c; } }; //---------------------------------- Cl_AAA AAA; //---------------------------------- void setup() { AAA.init(set1); //AAA.init(set2); //AAA.init(set3); } void loop() { } /**/Но обычно используют компиляцию по условиям. Так меньше памяти занимает
Спасибо, но это прямая противоположность задаче, у вас в оперативке хранятся сразу все три набора настроек для всех трех проектов. Задача-же не тратить оперативку совсем и с помошью шаблонного класса это получается. В реальности приходится перекраивать библиотеки, но это дело житейское.
constset_t setting[]прячте в PROGMEM. а в функции init() извлекайте. Все остальное не требует ОЗУ.ПС:#248
А еще проще используйте условную компиляцию
от сюда http://cpp.com.ru/shildt_spr_po_c/10/1005.html
пошли по кругу : я вам уже писал "Использовать PROGMEM тут не рационально т.к. придётся больше кода писать, больше флеша уйдёт на вызов pgm_read_xxx() и стека на вызов и на переменную в которую нужно читать из флеша."
макросы это суровое наследие C, в C++ лет 30 назад были придуманы шаблоны
больше флеша уйдёт на вызов pgm_read_xxx() и стека на вызов
А вы это проверяли?
Если "да" - на сколько больше?
-------------------------------------------
class Settings{