Форум: "Начинающим";
Текущий архив: 2011.12.04;
Скачать: [xml.tar.bz2];
Внизrecord в array of byte Найти похожие ветки
← →
Sega625 (2011-08-19 21:15) [0]Господа, всю голову сломал. Нужно довольно сложную структуру (record), cодержащую динамические массивы переложить в массив байтов. Вот сильно упрощенный пример кода:
procedure TForm1.Button1Click(Sender: TObject);
type
TRec = packed record
A: byte;
B: byte;
C: array[0..3] of byte;
D: array of byte;
E: byte;
end;
var
Size, n: WORD;
Rec: TRec;
Arr: array of byte;
begin
with Rec do
begin
A := 10;
B := 11;
C[0] := 20;
C[1] := 21;
C[2] := 22;
C[3] := 23;
SetLength(D, 6);
D[0] := 30;
D[1] := 31;
D[2] := 32;
D[3] := 33;
D[4] := 34;
D[5] := 35;
E := 40;
end;
Size := SizeOf(TRec)-4+Length(Rec.D);
SetLength(Arr, Size);
Move(Rec, Arr[0], Length(Arr));
// Arr := @Rec;
Memo1.Clear;
for n := 0 to Size-1 do
Memo1.Lines.Add(IntToStr(Arr[n]));
end;
Результат такой: 10 11 20 21 22 23 24 0 63 38 1 40 84 36
Я понимаю - так и должно быть: вместо самого динамического массива Rec.D записывается указатель на него. А вот как подобную структуру полностью отразить на массив байтов? Может какое хитрое приведение типов?
Заранее благодарю.
← →
Игорь Шевченко © (2011-08-19 21:46) [1]
> А вот как подобную структуру полностью отразить на массив
> байтов?
Глупый вопрос - а зачем такую структуру отражать на массив байтов ?
← →
Сергей М. © (2011-08-19 21:49) [2]
> полностью отразить
Коэффициент "отражения на массив байтов" должен быть равен единице.
Но это только в сказке.
← →
Palladin © (2011-08-19 22:58) [3]к сильно упрощенному примеру кода прилагаю сильноу прощенный путь к победе array + F1
← →
Sega625 (2011-08-19 23:04) [4]
> Глупый вопрос - а зачем такую структуру отражать на массив
> байтов ?
Мне нужно по MIDI (как sysex) передать в мой синтезатор немеренную структуру, содержащую информацию о песнях (кол-во нот, высота, уровни эффектов ... - для 16 треков). Ну Вы понимаете, что количество песен, нот в них и т.д. может быть различным. Драйвер MIDI хавает только array of char :(. Со статическими структурами - все отлично, а вот если она содержит динамические элементы - обломс... Вручную это почти не реально сделать и не красиво. С TMemoryStream тоже не получилось. Должно же быть какое-то решение.
> Коэффициент "отражения на массив байтов" должен быть равен
> единице.
> Но это только в сказке.
Фатализмом веет от вашего поста :( :)
← →
Sega625 (2011-08-19 23:11) [5]
> к сильно упрощенному примеру кода прилагаю сильноу прощенный
> путь к победе array + F1
Даже Гугль не помог, а Вы говорите F1... Тем более в D7SE :)
← →
Anatoly Podgoretsky © (2011-08-19 23:18) [6]Не понятно как ты пришел к этому 0 63 38 1
В коде таких данных нет
Может тебе по русски задать вопрос.
← →
Palladin © (2011-08-19 23:18) [7]вот мне гугль не помог скреситить IMultiStream (изобретение Micrisoft) к IStream (изобретение Microsoft), это да
а, знаешь, если ты не способен изучить результаты "dynamic array delphi", в том же гугле то может быть ну его нафик?
← →
Sega625 (2011-08-19 23:28) [8]
> Не понятно как ты пришел к этому 0 63 38 1
> В коде таких данных нет
> Может тебе по русски задать вопрос.
Я так понимаю это адрес-указатель на массив Rec.D (может быть любым), за тем идет Rec.E = 40, а потом 2 байта - мусор.
← →
Sega625 (2011-08-19 23:32) [9]
> Может тебе по русски задать вопрос.
Вот я и хочу чтобы вместо этих 4-х байт указателя было бы 6 байт нужного мне Rec.D.
← →
Игорь Шевченко © (2011-08-19 23:58) [10]
> Мне нужно по MIDI (как sysex) передать в мой синтезатор
> немеренную структуру
сделать отдельную функцию или у записи метод (D2005 и выше), который(ая) будет аккуратно укладывать нужные поля записи в байтовый массив, согласно требованиям sysex
ну что-то вродеtype
TRec = packed record
A: byte;
B: byte;
C: array[0..3] of byte;
D: array of byte;
E: byte;
end;
//Допускаю, что размер дин. массива 1 байт
function RecToBytes (R: TRect): PByte;
var
P: PByte;
begin
Result := PByte(GetMem(SizeOf(R) - SizeOf(R.D) + Length(R.D) + SizeOf(Byte));
P := Result;
Move(R.A, P^, SizeOf(R.A));
Inc(P, SizeOf(R.A));
Move(R.B, P^, SizeOf(R.B));
Inc(P, SizeOf(R.B));
Move(R.C, P^, SizeOf(R.C));
Inc(P, SizeOf(R.C));
Move(Byte(Length(R.D), P^, SizeOf(Byte));
Inc(P, SizeOf(Byte));
Move(R.D[0], P^, Length(R.D));
Inc(P, Length(R.D));
Move(R.E, P^, SizeOf(R.E));
end;
Написано на скорую руку для иллюстрации идеи
← →
Sega625 (2011-08-20 00:11) [11]
> сделать отдельную функцию или у записи метод (D2005 и выше),
> который(ая) будет аккуратно укладывать нужные поля записи
> в байтовый массив, согласно требованиям sysex
>
> ну что-то вроде
>
> type
> TRec = packed record
> A: byte;
> B: byte;
> C: array[0..3] of byte;
> D: array of byte;
> E: byte;
> end;
>
> //Допускаю, что размер дин. массива 1 байт
>
> function RecToBytes (R: TRect): PByte;
> var
> P: PByte;
> begin
> Result := PByte(GetMem(SizeOf(R) - SizeOf(R.D) + Length(R.
> D) + SizeOf(Byte));
> P := Result;
> Move(R.A, P^, SizeOf(R.A));
> Inc(P, SizeOf(R.A));
> Move(R.B, P^, SizeOf(R.B));
> Inc(P, SizeOf(R.B));
> Move(R.C, P^, SizeOf(R.C));
> Inc(P, SizeOf(R.C));
> Move(Byte(Length(R.D), P^, SizeOf(Byte));
> Inc(P, SizeOf(Byte));
> Move(R.D[0], P^, Length(R.D));
> Inc(P, Length(R.D));
> Move(R.E, P^, SizeOf(R.E));
> end;
>
> Написано на скорую руку для иллюстрации идеи
Вот это я и имел ввиду, когда писал - вручную. Похоже красивого решения не существует :(.
Спасибо Вам Игорь - попробую так и сделать.
← →
SQLEXPRESS (2011-08-20 00:58) [12]да нет же
все проще
по мотиву
http://delphimaster.net/view/15-1313045575/
← →
SQLEXPRESS (2011-08-20 01:03) [13]т.е. Tтип(Pointer(указатель_на_что_надо)) и не надо приводить ни к чему
делаем как удобно
если понял, конечно
← →
Германн © (2011-08-20 02:04) [14]
> SQLEXPRESS (20.08.11 01:03) [13]
>
> т.е. Tтип(Pointer(указатель_на_что_надо)) и не надо приводить
> ни к чему
> делаем как удобно
> если понял, конечно
>
Не понял.
← →
SQLEXPRESS (2011-08-20 02:37) [15]почему? надо передать - передаем
зачем "раскладывать в строку байт"?
type
TRec = packed record
A: byte;
B: byte;
C: array[0..3] of byte;
sizeD: Integer; //
D: array of byte;
E: byte;
end;
type
TForm1 = class(TForm)
btn1: TButton;
procedure btn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure showw(ar: Trec);
end;
var
Form1: TForm1;
r: TRec;
implementation
{$R *.dfm}
procedure TForm1.btn1Click(Sender: TObject);
begin
r.A := 1;
r.sizeD := 3;
SetLength(r.D, 3);
r.D[0] := 100;
r.D[1] := 11;
r.D[2] := 22;
showw(r);
end;
procedure TForm1.showw(ar: Trec);
var
i: Integer;
begin
for i := 0 to ar.sizeD - 1 do
ShowMessage(IntToStr( ar.D[i] ));
end;
← →
Германн © (2011-08-20 03:03) [16]
> SQLEXPRESS (20.08.11 02:37) [15]
Это решение уже представил ИШ.
Чем твоё решение лучше?
← →
SQLEXPRESS (2011-08-20 03:20) [17]проще читать
← →
Sega625 (2011-08-20 10:45) [18]Я надеялся на что-то вроде этого:
type
TRec = packed record
A: byte;
B: byte;
C: array[0..3] of byte;
D: array of byte;
E: byte;
end;
PRec = ^TRec;
var
Ar: array of byte;
R: TRec;
begin
R.A := 10; // Присвоение
bla-bla-bla // записи R
R.E := 40; // значений
SetLength(SizeOf(R) - SizeOf(R.D) + Length(R.D) * SizeOf(Byte));
PRec(Ar) := @R;
end;
Ну типа компилятор зная структуру TRec уложит значения куда нужно :)
На самом деле, как я уже писал, структура R сложнее и имеет в качестве элементов динамические массивы структур, которые в качестве элементов содержат тоже динамические массивы...
Она прекрасно заполняется из стандартного файла (.SNG если кому интересно) BlocReadами, поэтому добавление новых элементов (как то SizeD) крайне нежелательно. Еще нужно полученный массив байтов переконвертить из 8-байтного в 7-ми байтный, прикрутить хэдер и обставить по краям F0 и F7 (формат sysex) и запульнуть в драйвер миди, который в качестве аргумента принимает адрес массива и его длину. Вот. Еще нужно будет принимать из синтезатора в структуру, пересылать из структуры в файл, ну это уже другая история... :)
Это я написал лишь для полноты картины.
P.S Честно говоря не ожидал такого внимания к новичкам, спасибо.
← →
Inovet © (2011-08-20 11:15) [19]> [18] Sega625 (20.08.11 10:45)
> Она прекрасно заполняется из стандартного файла (.SNG если
> кому интересно) BlocReadами, поэтому добавление новых элементов
> (как то SizeD) крайне нежелательно
Ты что-то недопонимаешь. Или размер или признак конца должен быть.
Ты свой секвенсор что ли пишешь?
← →
sniknik © (2011-08-20 11:19) [20]> Я надеялся на что-то вроде этого:
сделай class + методы, и будет почти как ты хочешь... поработаешь за компилятор... ты же знаешь структуру + чего тебе надо. ->
> Ну типа компилятор зная структуру TRec уложит значения куда нужно :)
← →
Sapersky (2011-08-20 13:55) [21]Есть хакерский метод, который использует внутреннюю информацию компилятора для обработки управляемых типов (в т.ч. дин. массивов).
http://sapersky.narod.ru/files/TypInfoEx.rar
Скидывает результат в TStream, хотя не факт, что формат подойдёт (оно больше рассчитано на сериализацию, перед массивом пишет длину и т.д.).
Более прямой вариант - расширенная RTTI в D2010 и далее.
Или, возможно, проще пересмотреть структуру данных и вместо дин. массивов использовать статические макс. размера, если это не приведёт к чрезмерному перерасходу памяти.
← →
Sapersky (2011-08-20 14:00) [22]вместо дин. массивов использовать статические макс. размера
А, нет, всё равно нужна будет обработка вручную, чтобы "вырезать" данные текущего размера.
← →
Inovet © (2011-08-20 14:08) [23]> [21] Sapersky (20.08.11 13:55)
> Или, возможно, проще пересмотреть структуру данных
Мы не знаем, что там автор спрятал за A, B, C, D, E.
← →
sniknik © (2011-08-20 14:46) [24]>> Или, возможно, проще пересмотреть структуру данных
> Мы не знаем, что там автор спрятал за A, B, C, D, E.
по тому что показано -
вместоTRec = packed record
A: byte;
B: byte;
C: array[0..3] of byte;
D: array of byte;
E: byte;
end;
сделатьTRec = packed record
A: byte;
B: byte;
C: array[0..3] of byte;
E: byte;
D: array[0..MaxInt] of byte;
end;
как делали в паскале, до динамических массивов.
само собой самому выделять переменной только нужное количество памяти (/следить за размером)
рекогд "вытянется в линию", и тогда будет достаточно приведения типа... и массив байт не понадобится.
фактически это будет одно и тоже, можно переменные по absolute в одном месте располагать, типа одна указатель на рекорд другая на массив располагающиеся в одном адресе... так даже привидение типа не нужно будет.
← →
Сергей М. © (2011-08-20 19:55) [25]
> Драйвер MIDI хавает только array of char
Т.е. драйвер разработан именно в Delphi и никакие массивы кроме дельфийских динамических не признает ?
Свежо предание)..
← →
Германн © (2011-08-21 00:23) [26]
> Сергей М. © (20.08.11 19:55) [25]
Драйвер, очевидно, принимает только массив байт, который четко структурирован. Вот только автор пошел по пути наименьшего сопротивления.
← →
Anatoly Podgoretsky © (2011-08-21 08:36) [27]> Германн (21.08.2011 00:23:26) [26]
Ты туда не ходи, снег башка попадет.
← →
Sega625 (2011-08-22 18:14) [28]
> > [18] Sega625 (20.08.11 10:45)
> > Она прекрасно заполняется из стандартного файла (.SNG
> если
> > кому интересно) BlocReadами, поэтому добавление новых
> элементов
> > (как то SizeD) крайне нежелательно
>
> Ты что-то недопонимаешь. Или размер или признак конца должен
> быть.
В файле SNG есть адреса (смещения в файле) нужных мне блоков. Соответственно можно вычислить длину каждого блока. Естественно файл я пихаю в структуру вручную.
> Ты свой секвенсор что ли пишешь?
Да ну что Вы. Есть же неподражаемые Cubase, Logic, ProTools, CakeWalk и т.д. Идея была расширить дисплей моего синта (Korg Triton rack) до размеров моего монитора 20" :). Другими словами, сделать управление через компьютер по MIDI. Ну и добавить всякого приятного функционала. Например самоиграечной функции.
> по тому что показано -
> вместо
> TRec = packed record
> A: byte;
> B: byte;
> C: array[0..3] of byte;
> D: array of byte;
> E: byte;
> end;
> сделать
>
> TRec = packed record
> A: byte;
> B: byte;
> C: array[0..3] of byte;
> E: byte;
> D: array[0..MaxInt] of byte;
> end;
>
> как делали в паскале, до динамических массивов.
> само собой самому выделять переменной только нужное количество
> памяти (/следить за размером)
> рекогд "вытянется в линию", и тогда будет достаточно приведения
> типа... и массив байт не понадобится.
> фактически это будет одно и тоже, можно переменные по absolute
> в одном месте располагать, типа одна указатель на рекорд
> другая на массив располагающиеся в одном адресе... так даже
> привидение типа не нужно будет.
По данному примеру - хорошее решение. Но, даже если бы можно было бы менять местами элементы, при добавлении еще одного дин. элемента (а их там даже не 2), к сожелению, метод не работает. Как узнать конец 1-го и начало 2-го дин. массива?
> Т.е. драйвер разработан именно в Delphi и никакие массивы
> кроме дельфийских динамических не признает ?
>
> Свежо предание)..
Драйвер, я думаю, разработан в С++ :) Просто в файле MMSystem.pas (вроде так называется) портированы его функции и нужные структуры. Хотя, Вы - правы: драйверу нужен pchar, правда я не вижу в данном случае принципиальной разницы между pchar и array of char (byte).
> Вот только автор пошел по пути наименьшего сопротивления.
Просто обидно - все остальные структуры преобразовываются за 2-е строчки кода, а этой - функцию подавай или целый класс :). Ладно пошел я лепить функцию.
P.S. Спасибо всем огромное за помощь.
← →
sniknik © (2011-08-22 19:29) [29]> Как узнать конец 1-го и начало 2-го дин. массива?
если это реально "дин. массив" то легко, если "эмуляция" то размер тоже нужно "эмулировать". (почитай про дейфёвские строки как пример)
> портированы его функции и нужные структуры.
??? опля, оказывается все уже сделано до нас... а о чем мучения тогда? используй их, и все дела.
← →
Sega625 (2011-08-22 23:03) [30]Я понял Вашу идею (в своей извращенной интерпретации конечно :)) как-то так:
type
TRec = packed record
A: byte;
B: byte;
C: array[0..3] of byte;
E: byte;
D: array[0..MAXWORD] of byte;
end;
var
R: TRec;
Ar: array of byte;
begin
with R do
begin
// Присваиваем значения R
end;
SetLength(Ar, RealSize); // Я же знаю реальный размер дин. массива
Ar := @R;
end;
и если будет еще один д. массив D1(да любой элемент после D), в ряд структура уже не выложится. Или я не правильно понял?
> почитай про дейфёвские строки как пример
Вы имеете в виду, что в самой строке уже есть ее размер? Возможно я начинаю подготавливать себя к мысли вставить размеры динамических структур в саму структуру :).
> > портированы его функции и нужные структуры.
> ??? опля, оказывается все уже сделано до нас... а о чем
> мучения тогда? используй их, и все дела.
Возможно я не правильно выразился, я имел ввиду, что портированы функции и структуры для работы с миди-драйвером с сишных хэдеров.
Вот например функц. для посылки сисекса:
midiOutLongMsg(DevID, @buffMIDIHDR, Sizeof(MIDIHDR));
где:
buffMIDIHDR: MIDIHDR;
MIDIHDR = record
lpData: PChar; { pointer to locked data block }
dwBufferLength: DWORD; { length of data in data block }
dwBytesRecorded: DWORD; { used for input only }
dwUser: DWORD; { for client"s use }
dwFlags: DWORD; { assorted flags (see defines) }
lpNext: PMidiHdr; { reserved for driver }
reserved: DWORD; { reserved for driver }
dwOffset: DWORD; { Callback offset into buffer }
dwReserved: array[0..7] of DWORD; { Reserved for MMSYSTEM }
end;
lpData - тот самый злаполучный массив с прикрученным хэдером и переконверченный в формат сисекс.
dwBufferLength - его длина.
Остальное - не важно.
← →
sniknik © (2011-08-22 23:38) [31]> lpData: PChar;
блин, это же указатель, вот и присвой как есть указатель на структуру. если структура правильная то он поймет, как бы ты ее в дельфях не затипизировал...
тип это фикция, чисто чтобы тебе понятнее, а на деле все строчка байт... это если грубо говоря.
> dwBufferLength - его длина.
ну вот и длинна оказывается есть...
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2011.12.04;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.005 c