Найти тему

Ссылочные типы в Codesys. Ссылки и указатели в Codesys v3.5.

Оглавление

В этой статье будет про ссылки и указатели в Codesys. Мы разберемся по синтаксису, про принципы работы что с одним, что с другим, и рассмотрим несколько примеров использования в промышленном программировании для ПЛК.

Хочет заметить, что когда-то давно я уже писал сумбурную статью с примерами оторванными от жизни. Теперь все более детально.

Ссылочный тип

Ссылочный тип — это тип данных, в котором хранятся ссылки на данные. Когда в обычной переменной хранится само значение. Разные переменные ссылочного типа могут ссылаться на одну и туже переменную, которая хранит само значение.

В промышленном программировании ссылочный тип является расширением стандарта IEC 61131-3, а это значит что работа с ним очень сильно зависит от среды разработки.

ВНИМАНИЕ!!!Работы с ссылочным типом не является безопасной.

В Codesys V3.5 у на сесть две переменные ссылочного типа это Pointer и Reference.

Refetence(Ссылка)

Reference — хоть и является ссылочным типом данных, но он более безопасный чем Pointer и имеет ряд свойств.

  • Не требует явного разыменовывания для доступа к значению.
  • Данный тип проверяется при компиляции на соответствие базовому типу
СИНТАКСИС<identifier> : REFERENCE TO <data type>

Вы не можете объявить ссылки следующими способами:

  • REFERENCE TO REFERENCE
  • или ARRAY OF REFERENCE
  • или .POINTER TO REFERENCE

Более того, вы не можете объявить ссылку на битовую переменную.

Присваивание происходит через REF=

И самая хорошая вещь -это проверка типа

<Boolean variable> := __ISVALIDREF(<with REFERENCE TO <data type> declared identifier);

Немного практики

Возьмем пример высосанный из пальца, но все же имеющий право на жизнь. Мы будем, как и всегда. писать в переменные, которые объявим в VAR_IN.

На изображении представлен код блока. Делает он максимальную ерундистику. Мы проверяем входные данные, что там точно целочисленное и прибавляем к нему единицу.

код вызова функции
код вызова функции
результат выполнения
результат выполнения

Надеюсь, никому не надо проводить опыт, что если мы просто запишем в VAR_IN переменную типа со значением, то у нас ничего не запишется?

КОГДА ПРИМЕНЯТЬ?

Вот это мне больше всего нравится. В чем смысл если мы можем просто обратиться к переменной VAR_IN_OUT, А я вам отвечу — да никакого. Все переменные, которые объявлены в разделе VAR_IN_OUT — имеют ссылочный тип.

Но пользуюсь ли я им? Да. Везде где мне надо в ФБ загнать структуру, дабы не создавать копии. Плюс я явно не хочу неявного использования ссылочного типа.

Pointer(Указатель)

Pointer — ссылочный тип данных, который хранит в себе, если уж быть точным, адрес первой ячейки в памяти где находится объект на который он ссылается.

СИНТАКСИС<identifier>: POINTER TO <data type | function block | program | method | function>;

Адрес получаем благодаря команде ADR(), чтобы получить данные нам надо разыменовать указатель с помощью символа ^

А теперь, я предлагаю нам немного побыть компиляторами, чтобы понять магию указателей, но чтобы трюк сработал давайте закрепим:

  • Содержит адрес первой ячейки где хранится переменная
  • Компилятор не может проверить тип, на который ссылается указатель
ptrReal: POINTER TO REAL;

Структура, что объявлена выше при расшифровки будет говорить следующее компилятору: «Привет меня зовут ptrReal и я храню в себе адрес переменной типа Real. Если где-то в коде меня будет разыменовывать возьми пожалуйста меня и три следующих байта данных и представь нас как REAL»

А дальше мы приведем банальный пример где покажем все адреса.

-4

Теперь давайте присвоим через разыменовывание какое-нибудь значение.

-5

Можно заметить что rValue теперь имеет значение 7.2, но давайте присвоим 255)

-6

Как можно заметить получаем то, что и ожидается. Но мы же помним, что говорит указатель компилятору. Давайте сменим тип указателя.

-7

И вот чем они опасны. Компилятору все равно на какой тип вы ссылаетесь. Вот по этому работа с указателями является очень опасной и вот тут вы можете себе выстрелить в ногу.

ПРАКТИЧЕСКОЕ ПРИМЕНЕНИЕ УКАЗАТЕЛЕЙ

Указатели применяются везде где нам требуется прямая работа с памятью, итерация по памяти и конверсии значений.

Конвертация значений

А почему бы и нет? что надо знать про конвертацию: во-первых, одинаковый размер(размер в байтах можно быстро глянуть через SIZEOF()), во вторых — все.

Делаем указатель на нужный нам тип данных, присваиваем ему старый тип данных и потом присваиваем в нужную нам переменную, ну или используем дальше этот указатель.

Щас будет пример, и чтобы показать что он правильно работает мы конвертируем еще значение через union.

-8

Работа с буферами данных

В основе своей буфер — это массив типа BYTE. Но вот данные там всегда максимально разные, но и некоторые вещи с массивом делать проще через указатели.

Всегда, когда работает с массивами или буфером через указатель проверяйте длину данных, которые вы туда записываете или считываете, чтобы не выйти за пределы буфера или массива.ВАМ ТАМ НЕ РАДЫ!

Что же за операции становятся гораздо проще.

  1. Очистка буфера.
    Я надеюсь вы чистите буфер приема и передачи перед новым циклом. Лично я -нет! пока не сталкиваюсь с проблемой парсинга запросов, где конец моей строки ищу методом =16#00
-9

2. Формирование буфера на отправку или прием.

Грубо говоря проводим сериализация и десериализация данных. Если потребуется пример, то дайте знать.

3. Парсинг

А это самое интересное. Существует много протоколов, где ты не знаешь с какого индекса начнется новый блок или его длину, или разные системы отчетов, где проще пользоваться именно что математикой связанной с байтами и указателями.

кусок обработки http запроса
кусок обработки http запроса

ФБ и сложные структуры данных

Я думаю что это тоже отдельная тема для разговоров. Но мы можем делать максимально возможные универсальные входа/выхода для функциональных блоков. Передавая значения как указатель и тип данных. или передавая два указателя на тип данных и функцию необходимую нам или можем еще как-нибудь извратиться.

ИТОГО

Стоит ли немного отдать времени указателям и ссылкам — да! Это весьма мощный инструмент, который позволяет сделать очень много вещей в хороших руках. Например вы можете поиграть с динамическим выделением памяти или постройки каких-то особенных фишек. Так что дерзайте.

А я напоминаю, что если у вас есть вопросы или какие-то замечания, то пишите на почту — info@engcore.ru