Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Сб ноя 24, 2012 14:02:39

Сообщение matrex »

Всем привед!

Как правильно использовать глобальные переменныйе. В проекте (Arduino, PlatformIO) использую библиотеку для работы с дисплеем U8glib. Объявляю так:

Код: Выделить всё

main.cpp

#include <Arduino.h>
#include "U8glib.h"

U8GLIB_ST7920_128X64_1X u8g(10);

void setup()
{
}
void loop()
{
}
В принципе все работает. Сейчас хочу разнести функциональность при работе с дисплеем по разным модулям, например для работы с меню в menu.cpp, для рисования графиков - chart.cpp, для рисования таблиц - table.cpp и т.д. Делал примерно так:

Код: Выделить всё

chart.cpp
 
#include <Arduino.h>
#include "U8glib.h" 

U8GLIB_ST7920_128X64_1X screen;

void chartInit(U8GLIB_ST7920_128X64_1X v_screen)
{
    screen = v_screen;
}

void chartUint8(uint8_t v_x, uint8_t v_y, const uint8_t v_s)
{
    u8g.setPrintPos(v_x, v_y);
    u8g.print(v_s);
}

void chartUint8_v1(U8GLIB_ST7920_128X64_1X v_screen, uint8_t v_x, uint8_t v_y, const uint8_t v_s)
{
    v_screen.setPrintPos(v_x, v_y);
    v_screen.print(v_s);
}
Как достучаться до переменной u8g, объявленной в модуле main.cpp из модуля chart.cpp? Испробовал три варианта - работает только chartUint8_v1, но такой подход меня не очень устраивает. Я хочу или на старте задать ссылку на класс (chartInit) и потом его использовать, или использовать переменю глобально (chartUint8).
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Ключевое слово extern в заголовочном файле спасёт отца программирования.
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Как правильно использовать глобальные переменныйе.
Лучше через функции доступа к ним. Инкапсуляция всё же полезна.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Это и так уже объекты.
Реклама
Эиком - электронные компоненты и радиодетали
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Сб ноя 24, 2012 14:02:39

Сообщение matrex »

Если бы было все так просто, то отец программирования уже бы давно бы кушал в ресторанах во фраке и белых перчатках ))) Я может ересь ща скажу, но main не имеет заголовка. Указание в заголовке chart.h дает ошибку... Если extern объявить в main.cpp - тоже ошибка.
СпойлерИзображение
Кстати, я нигде примера не нашел подобного. Все тупо юзают майн и не парятся...
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

extern "обещает" компилятору, что переменная такого типа есть где-то в другой единице трансляции. Там где объект определяется extern не нужен. Ну это же основы, читаем K&R на ночь до просветления.

Кстати, вы так лихо объекты присваиваете и передаёте в функции. Там накладные расходы просто ужас. Не надо так делать. Создайте один глобальный объект и работайте с ним.
Последний раз редактировалось VladislavS Пт апр 24, 2020 17:29:23, всего редактировалось 1 раз.
Реклама
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Сб ноя 24, 2012 14:02:39

Сообщение matrex »

[uquote="da-nie",url="/forum/viewtopic.php?p=3832660#p3832660"]
Как правильно использовать глобальные переменныйе.
Лучше через функции доступа к ним. Инкапсуляция всё же полезна.[/uquote]

Это как? Создать модуль, в котором создать класс работы с дисплеем, в модуле сделать функцию на получение ссылки на класс и ее юзать в других модулях? Что то типа

Код: Выделить всё

lcd.cpp

#include <Arduino.h>
#include "U8glib.h" 

U8GLIB_ST7920_128X64_1X screen;

U8GLIB_ST7920_128X64_1X  getLCD()
{
    return screen;
}
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Это и так уже объекты.
Так всё равно. Сами-то они доступны вне модуля станут. А модуль лучше бы сделать закрытым, чтобы его состояние менять только функциями, специально для этого предназначенными.
Я может ересь ща скажу, но main не имеет заголовка.
И слава богу. :) Вы нужному модулю подключите модуль, где этот ваш объект определён и описывается и укажите сам объект как extern.

А вместо объектов в функции ссылки (уж не знаю, что у вас за язык - Си или С++ там) или указатели на объекты передавайте.
Это как? Создать модуль, в котором создать класс работы с дисплеем, в модуле сделать функцию на получение ссылки на класс и ее юзать в других модулях? Что то типа
Да. Только лучше в вашем случае либо ссылку, либо указатель возвращать. Правда, модуль отдельный для этого можно и не создавать, ограничившись созданием объекта в одном из существующих модулей.
Но если есть желание, можно и синглетон сделать (посмотрите этот паттерн, хорошая штука в данном случае). Я правда, не знаю, много ли у вас памяти на такие фокусы.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Нельзя так делать!!! U8GLIB_ST7920_128X64_1X это класс. При его копировании, передаче в и возврате из функции создаются его копии, вызываются конструкторы копирования и присваивания, деструкторы. Любой микроконтроллер можно "положить" на лопатки.

PS: Ага, синглтон человеку, который про extern не слышал. И С++ там, неужели не видно создание объектов и вызов их методов?
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

И С++ там, неужели не видно создание объектов и вызов их методов?
Меня очень смущают указание на arduino и Си++ в проекте одновременно. :oops: Потому я и не понимаю, что там такое за мутация. Может, ардуино ide что-то своё умеет, похожее на Си++? Я с ней не работал никогда и ничего про неё не знаю. И я ещё AVR с килобайтом ОЗУ на Си++ не запускал. Вот STM - другое дело.
Последний раз редактировалось da-nie Пт апр 24, 2020 17:42:23, всего редактировалось 1 раз.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Ардуина на С++ написана. Это новость?
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Ардуина на С++ написана. Это новость?
Для меня - да. Я же говорю, я именно с ардуиной дел никогда не имел. И не слышал, чтобы ардуинщики, скажем, winavr запускали - строго некую arduino ide. esp-шники, например, тоже не спешат ставить SDK и Си - все практически пользуются lua, at-командами и микропитоном. Плюс некая привязка к ардуине.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

В arduino ide компилятор gcc, который С++ только в путь. Сам по себе C++ не даёт накладных расходов, если с головой подходить, а не так как matrex.
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Сам по себе C++ не даёт накладных расходов
А это смотря что делать. :) Может, мне полиморфизм нужен будет (а, собственно, привязку к разным дисплеям так очень удобно делать). А тут уже vtable появляется.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

С дуру и хрен сломать можно. Я же говорю - с головой. А с головой даже и экономить можно научиться.
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Сб ноя 24, 2012 14:02:39

Сообщение matrex »

Из всего сказанного понял и сделал отдельный модуль:

Код: Выделить всё

#include <Arduino.h>
#include "U8glib.h" // Подключаем библиотеку U8glib
#include "Rtc_Pcf8563.h" // Часики

#ifndef _CLASSES_
#define _CLASSES_

U8GLIB_ST7920_128X64_1X u8g(10);
Rtc_Pcf8563 rtc;

#endif
Размер результирующего файла не изменился, но теперь подключая этот модуль к другим я могу обратиться к u8g и rtc. Идеологически это правильно я так понимаю? Завтра проверю в железе. Спасибо за помощь.
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="matrex",url="/forum/viewtopic.php?p=3832691#p3832691"]Идеологически это правильно я так понимаю?[/uquote]Нет. Читайте про ключевое слово extern, для чего оно нужно и как применяется. Ну правда, это же основы, их надо знать обязательно.
Первый раз сказал Мяу!
Сообщения: 28
Зарегистрирован: Сб ноя 24, 2012 14:02:39

Сообщение matrex »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3832694#p3832694"][uquote="matrex",url="/forum/viewtopic.php?p=3832691#p3832691"]Идеологически это правильно я так понимаю?[/uquote]ключевое слово extern, для чего оно нужно и как применяется. Ну правда, это же основы, их надо знать обязательно.[/uquote]

Да не требуется там extern перестает компилироваться тогда. По ощущениям эти классы уже объявлены как extern сами по себе...

Вот именно что основы я понимаю, знаю и понимаю ООП. Но основная среда разработки у меня другая. Все мои примеры основаны на опыте работы с Delphi, а там мои примеры которые выше, но адаптированные под С++, считаются логичными и не вызывают никаких проблем и накладных расходов... Для меня вся проблема только в неожиданных"сюрпризах", "хитрых" директивах и структуре проекта...
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Из всего сказанного понял и сделал отдельный модуль:
Нет, не так. В h-файлах ничего не должно создаваться. Там только описание того, что модуль даёт на экспорт.
Всё созданное лежит в c-файлах модулей.

display.h

Код: Выделить всё

#ifndef DISPLAY_H
#define DISPLAY_H

#include <Arduino.h>
#include "U8glib.h"

U8GLIB_ST7920_128X64_1X* GetDisplayPtr(void);

#endif
display.c

Код: Выделить всё

#include "display.h"

static U8GLIB_ST7920_128X64_1X Display;

U8GLIB_ST7920_128X64_1X* GetDisplayPtr(void)
{ 
 return(&Display);
}
Да не требуется там extern перестает компилироваться тогда. По ощущениям эти классы уже объявлены как extern сами по себе...
extern там можно. Работать будет. Можно даже extern функций делать. Вы просто ещё не освоились с концепцией заголовок-реализация. Поэтому ставите extern не туда и подключаете не то (и создали, наверняка, объект в заголовочном файле). Но это плохой стиль. Приводит он к тому, что у вас состояние модуля (речь не о вашем классе дисплея - тут это действительно пофигу, он у вас один, но вот в будущем не привыкайте к такому стилю) меняется с разных точек. А если вы измените поведение? А если оно начнёт меняться непредсказуемо? Вот поэтому глобальные переменные вредны. Их стоит использовать разве что при ну очень жесткой экономии ресурсов.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="matrex",url="/forum/viewtopic.php?p=3832700#p3832700"]Да не требуется там extern перестает компилироваться тогда.[/uquote]Ну не требуется так не требуется. Трахайтесь дальше вместо того чтобы одну страницу по ссылке про extern изучить.
[uquote="matrex",url="/forum/viewtopic.php?p=3832700#p3832700"]По ощущениям эти классы уже объявлены как extern сами по себе...[/uquote] Ещё бы понятие класс и объект научиться отличать.
[uquote="matrex",url="/forum/viewtopic.php?p=3832700#p3832700"]Вот именно что основы я понимаю, знаю и понимаю ООП.[/uquote]Это видно, по тому как лихо вы объекты копируете и из/в функции передаёте.
[uquote="matrex",url="/forum/viewtopic.php?p=3832700#p3832700"]Все мои примеры основаны на опыте работы с Delphi,[/uquote]Ну ничего не поделаешь, взялись за С++, будьте добры изучить и подчиняться его правилам.

Добавлено after 4 minutes 24 seconds:
[uquote="da-nie",url="/forum/viewtopic.php?p=3832702#p3832702"]Вот поэтому глобальные переменные вредны. Их стоит использовать разве что при ну очень жесткой экономии ресурсов.[/uquote]Тут не просто переменные, а объект неизвестного размера. Где же его ещё создавать, не в стеке или куче же. Да ещё чтобы доступен из других единиц трансляции был.
Ответить

Вернуться в «Разные вопросы по МК»