Просмотр полной версии : Ссылка на массив в структуре.
Привет.
Есть структура:
TYPE STRUCTURA:
STRUCT
b1:BYTE:=1;
b2:BYTE:=2;
w1:WORD:=65535;
b3:BYTE:=3;
cb4:BYTE:=4;
p:POINTER TO ARRAY OF BYTE;(*Здесь хочу сделать ссылку на массив не фиксированной длины*)
b4:BYTE:=5;
b5:BYTE:=6;
END_STRUCT
END_TYPE
Надо ссылку на массив, массивов у меня 3 шт.
buff1: ARRAY [1..10] OF BYTE;(*Массив №1*)
buff2: ARRAY [1..20] OF BYTE;(*Массив №2*)
buff3: ARRAY [1..30] OF BYTE;(*Массив №3*)
S:STRUCTURA;(*Объявил структуру*)
x:byte:=0; (*для свитча*)
Так вот, я хочу менять ссылку на любой из этих массивов. Как так сделать?
CASE x OF:
1:S.p:=ADR(buff1);
2:S.p:=ADR(buff2);
3:S.p:=ADR(buff3);
END_CASE;
POINTER TO ARRAY[0..0] OF BYTE;
И не путайте ссылку с указателем. Разные вещи. Ссылка (reference) это привязанное к переменной имя (в IEC 61131 у переменных может быть только одно имя, поэтому о ссылках ничего не говорится). Указатель (pointer) — самостоятельная ссылка (в 61131 тоже не оговаривается, является кодесисовским расширением).
POINTER TO ARRAY[0..0] OF BYTE;
И не путайте ссылку с указателем. Разные вещи. Ссылка (reference) это привязанное к переменной имя (в IEC 61131 у переменных может быть только одно имя, поэтому о ссылках ничего не говорится). Указатель (pointer) — самостоятельная ссылка (в 61131 тоже не оговаривается, является кодесисовским расширением).
Понял, спасибо, сейчас буду пробовать.
p:POINTER TO ARRAY OF BYTE;(*Здесь хочу сделать ссылку на массив не фиксированной длины*)
Тут надо бы подумать. Если размер структуры изменится, то в симуляторе и в контроллере будет по разному работать. Надо будет учесть выравнивание. Для корректной работы в контроллере структура должна быть кратна 4 байтам. Но могу и ошибаться.
Тут надо бы подумать. Если размер структуры изменится, то в симуляторе и в контроллере будет по разному работать. Надо будет учесть выравнивание. Для корректной работы в контроллере структура должна быть кратна 4 байтам. Но могу и ошибаться.
Да, я почитал форум и проблемы увидел.
Делаю всё только онлайн в плк.
Всё равно схитрить не получилось со структурой.
В общем это всё нужно мне для клиент сокета.
Цель была такая, имеется несколько массивов, вот их указатель я и хотел подсовывать в структуру, а структуру
скармливать в SysSockSend.
TYPE STRUCTURA:
STRUCT
b1:BYTE:=1;
b2:BYTE:=2;
w1:WORD:=65535;
b3:BYTE:=3;
cb4:BYTE:=4;
p:POINTER TO ARRAY[0..0] OF BYTE;
b4:BYTE:=5;
b5:BYTE:=6;
END_STRUCT
END_TYPE
var
S:STRUCTURA;(*Объявил структуру*)
x:byte:=0; (*для свитча*)
buff1: ARRAY [1..10] OF BYTE;(*Массив №1*)
buff2: ARRAY [1..20] OF BYTE;(*Массив №2*)
buff3: ARRAY [1..30] OF BYTE;(*Массив №3*)
POINT1:POINTER TO STRUCTURA;
end_var
CASE x OF:
1:S.p:=ADR(buff1);
2:S.p:=ADR(buff2);
3:S.p:=ADR(buff3);
END_CASE;
POINT1:=ADR(S);
SysSockSend(Socket,POINT1,SIZEOF(POINT1^),0);
В структуре указатель на массив, этот указатель хотел динамически менять,
но чтобы отправлялась структура вместе с массивом.
не получилось... понимаю почему, не понимаю как решить наиболее просто.
Да, наивно)) SysSockSend не смотрит, что у вас там в структуре. Для неё это плоский массив байтов, в том числе поле-указатель.
Заведите один достаточно большой буфер и перед отправкой копируйте в него всё, что душе угодно по любым условиям. Функция SysMemCpy из библы SysLibMem вам в помощь.
Да, наивно)) SysSockSend не смотрит, что у вас там в структуре. Для неё это плоский массив байтов, в том числе поле-указатель.
Заведите один достаточно большой буфер и перед отправкой копируйте в него всё, что душе угодно по любым условиям. Функция SysMemCpy из библы SysLibMem вам в помощь.
Да, про буфер думал изначально, откажусь от структуры и сделаю всё через массив.
Всем спасибо.
А если так:
TYPE STRUCTURA:
STRUCT
b1:BYTE:=1;
b2:BYTE:=2;
w1:WORD:=65535;
b3:BYTE:=3;
cb4:BYTE:=4;
p:POINTER TO BYTE;
b4:BYTE:=5;
b5:BYTE:=6;
END_STRUCT
END_TYPE
var
S:STRUCTURA;(*Объявил структуру*)
x:byte:=0; (*для свитча*)
buff1: ARRAY [1..10] OF BYTE;(*Массив №1*)
buff2: ARRAY [1..20] OF BYTE;(*Массив №2*)
buff3: ARRAY [1..30] OF BYTE;(*Массив №3*)
POINT1:POINTER TO STRUCTURA;
end_var
CASE x OF:
1:S.p:=ADR(buff1[1]);
2:S.p:=ADR(buff2[1]);
3:S.p:=ADR(buff3[1]);
END_CASE;
POINT1:=ADR(S);
SysSockSend(Socket,POINT1,SIZEOF(POINT1^),0);
Опа, так, ведь,
SysSockSend(Socket,POINT1,SIZEOF(POINT1^),0);
видит только указатель на массив, сам массив эта функция не видит. Массив должен быть в составе самой структуры и определятся до использования функции SysSockSend.
Давайте так:
TYPE STRUCTURA:
STRUCT
b1:BYTE:=1;
b2:BYTE:=2;
w1:WORD:=65535;
b3:BYTE:=3;
cb4:BYTE:=4;
buff: ARRAY[1..30] TO BYTE;
size_buff:BYTE;
b4:BYTE:=5;
b5:BYTE:=6;
END_STRUCT
END_TYPE
var
S:STRUCTURA;(*Объявил структуру*)
x:byte:=0; (*для свитча*)
buff1: ARRAY [1..10] OF BYTE;(*Массив №1*)
buff2: ARRAY [1..20] OF BYTE;(*Массив №2*)
buff3: ARRAY [1..30] OF BYTE;(*Массив №3*)
POINT1:POINTER TO STRUCTURA;
i:BYTE;
end_var
CASE x OF:
1:S.size_buff=10;
FOR i:=1 TO 10 DO
S.buff[i]:=buff1[i];
END_FOR
2:S.size_buff=20;
FOR i:=1 TO 20 DO
S.buff[i]:=buff1[i];
END_FOR
3:S.size_buff=30;
FOR i:=1 TO 30 DO
S.buff[i]:=buff1[i];
END_FOR
END_CASE;
POINT1:=ADR(S);
SysSockSend(Socket,POINT1,SIZEOF(POINT1^),0);
А на выходе смотреть размер массива и сам массив.
:) так Вы когда код написали, надо было его сперва проверить а потом аыкладывать
в таких случаях резервируют место по максимальному размеру массива и добавляют переменную сколько елементов будет в массиве,на другой стороне будет проще определить сколько взять данных
В принципе идея нравится, кроме вложенных циклов и выровнять структуру скорее всего надо будет. Я рассчитывал на SizeOf(buff) MOD 4 = 0;
Спасибо за идею, буду завтра с утра пробовать.
а на другой то стороне кто принимает данные, почти все ЯВУ понимают стандарт JSON, может в него все сформировать и не парится
Давайте так:
TYPE STRUCTURA:
STRUCT
...
buff: ARRAY[1..30] TO BYTE;
size_buff:BYTE;
...
END_STRUCT
END_TYPE
var
S:STRUCTURA;(*Объявил структуру*)
x:byte:=0; (*для свитча*)
buff1: ARRAY [1..10] OF BYTE;(*Массив №1*)
..
buff3: ARRAY [1..30] OF BYTE;(*Массив №3*)
POINT1:POINTER TO STRUCTURA;
i:BYTE;
end_var
CASE x OF:
1:S.size_buff=10;
FOR i:=1 TO 10 DO
S.buff[i]:=buff1[i];
END_FOR
2:S.size_buff=20;
FOR i:=1 TO 20 DO
S.buff[i]:=buff1[i];
END_FOR
3:S.size_buff=30;
FOR i:=1 TO 30 DO
S.buff[i]:=buff1[i];
END_FOR
END_CASE;
POINT1:=ADR(S);
SysSockSend(Socket,POINT1,SIZEOF(POINT1^),0);
Ну и в чем тогда смысл плавающего размера массива ?
TYPE TBUF
ARRAY[1..30] TO BYTE;
END_TYPE
TYPE STRUCTURA:
STRUCT
...
size_buff:BYTE;
buff: TBUF;
...
END_STRUCT
END_TYPE
var
S:STRUCTURA;(*Объявил структуру*)
x:byte:=0; (*для свитча*)
buff : ARRAY [1..3] OF TBUF(*Все массивы. Запас пофиг. Тут сэкономленное ни кому не нужно*)
end_var
x := limit(1,x,3); //чуть контроля
S.size_buf :=(x - 1) * 10;
S.buff := buf[i]; //не все ли равно что скопировано 30 байт если приемник знает size_buf ?
SysSockSend(Socket, adr(s), SIZEOF(s), 0);
Когда размер плавающий, это:
1.Или отправку мастерят в отдельный буфер - Yegor уже сказал
2.Или реализуют за запасом по максимуму - Vodav, но смысл в динамике ?
3.Или плавающую часть держат в конце и сам объект таскают динамически по куче
4.Отправляют друг за другом - если позволяет логика обработки на другом конце
5.Или JSON - Capzap предложил
Вариант симбиоза 1 и 3
TYPE STRUCTURA:
STRUCT
... //заголовок вообще без буфера
szBuf:BYTE; //только размер, а буфера нету
END_STRUCT
END_TYPE
---------
function Create : pointer to STRUCTURA //создаем и заполняем
var_input
h : STRUCTURA;
pBuf : dword;
szBuf : byte;
end_var
Create := SysMemAlloc(sizeof(h) + szBuf); //с хвостиком !!
Create^ := h; //копируем, но в szBuf - шняга
Create^.szBuf := szBuf; //теперь - хорошо
SysMemCpy(Create + sizeof(h), pBuf, szBuf); //и сами данные
---------
---------
function Destroy : bool //уничтожаем, причем размер - в самой структуре
var_input
pBuf : pointer to STRUCTURA;
end_var
SysMemFree(pBuf,sizeof(pBuf^) + pBuf^.szBuf)); //о хвостике - помним
--------
var
S : STRUCTURA;(*Объявил структуру*)
x : byte:=0; (*для свитча*)
buff1 : ... //тип пофиг
buff2 : ... //тип пофиг, и тип buff1 тоже пофиг
..
p : pointer to STRUCTURA; //здесь и вроде нетипизированного указателя
end_var
p := 0; //от игривых рук
case x of
1: p := Create(s,adr(buff1),sizeof(buff1));
2: p := Create(s,adr(buff2),sizeof(buff2));
..
end_case
if p > 0 then //от игривых рук
SysSockSend(Socket,p,sizeof(s) + p^.szBuf,0);
Destroy(p);
end_if
мелкие ошибки - возможны, исправите сами если юзать будете
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot