Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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.55 MB
Время: 0.004 c
1-1276169691
kukuruza
2010-06-10 15:34
2011.12.04
Может TerminateProcess вызызвать BSOD? А то система падает.


15-1313092214
Медвежонок Пятачок
2011-08-11 23:50
2011.12.04
большой гудронный кошмайдер. комнатный вариант.


15-1309448004
R_R
2011-06-30 19:33
2011.12.04
Фундаментальные шахматы...


15-1312959982
stas
2011-08-10 11:06
2011.12.04
DirectX вывести фигуру или текст на рабочий стол


2-1313476457
Cobalt
2011-08-16 10:34
2011.12.04
Left side cannot be assigned to (D2007)





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский