Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

record в array of byte [D7]


Страницы:   1 2

Sega625 ©   (2011-08-19 21:15:00) 

Господа, всю голову сломал. Нужно довольно сложную структуру (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 140 84 36

Я понимаю - так и должно быть: вместо самого динамического массива Rec.D записывается указатель на него. А вот как подобную структуру полностью отразить на массив байтов? Может какое хитрое приведение типов?

Заранее благодарю.


sniknik   (2011-08-22 23:38:00) [1]

> lpData: PChar;
блин, это же указатель, вот и присвой как есть указатель на структуру. если структура правильная то он поймет, как бы ты ее в дельфях не затипизировал...
тип это фикция, чисто чтобы тебе понятнее, а на деле все строчка байт... это если грубо говоря.

> dwBufferLength - его длина.
ну вот и длинна оказывается есть...


Sega625   (2011-08-22 23:03:00) [2]

Я понял Вашу идею (в своей извращенной интерпретации конечно :)) как-то так:

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 19:29:00) [3]

> Как узнать конец 1-го и начало 2-го дин. массива?
если это реально "дин. массив" то легко, если "эмуляция" то размер тоже нужно "эмулировать". (почитай про дейфёвские строки как пример)

> портированы его функции и нужные структуры.
??? опля, оказывается все уже сделано до нас... а о чем мучения тогда? используй их, и все дела.


Sega625   (2011-08-22 18:14:00) [4]


> > [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. Спасибо всем огромное за помощь.


Anatoly Podgoretsky   (2011-08-21 08:36:00) [5]

> Германн  (21.08.2011 00:23:26)  [26]

Ты туда не ходи, снег башка попадет.


Германн   (2011-08-21 00:23:00) [6]


> Сергей М. ©   (20.08.11 19:55) [25]

Драйвер, очевидно, принимает только массив байт, который четко структурирован. Вот только автор пошел по пути наименьшего сопротивления.


Сергей М.   (2011-08-20 19:55:00) [7]


> Драйвер MIDI хавает только array of char


Т.е. драйвер разработан именно в Delphi и никакие массивы кроме дельфийских динамических не признает ?

Свежо предание)..


sniknik   (2011-08-20 14:46:00) [8]

>> Или, возможно, проще пересмотреть структуру данных
> Мы не знаем, что там автор спрятал за 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 в одном месте располагать, типа одна указатель на рекорд другая на массив располагающиеся в одном адресе... так даже привидение типа не нужно будет.


Inovet   (2011-08-20 14:08:00) [9]

> [21] Sapersky   (20.08.11 13:55)
> Или, возможно, проще пересмотреть структуру данных

Мы не знаем, что там автор спрятал за A, B, C, D, E.


Sapersky   (2011-08-20 14:00:00) [10]

вместо дин. массивов использовать статические макс. размера

А, нет, всё равно нужна будет обработка вручную, чтобы "вырезать" данные текущего размера.


Sapersky   (2011-08-20 13:55:00) [11]

Есть хакерский метод, который использует внутреннюю информацию компилятора для обработки управляемых типов (в т.ч. дин. массивов).
http://sapersky.narod.ru/files/TypInfoEx.rar
Скидывает результат в TStream, хотя не факт, что формат подойдёт (оно больше рассчитано на сериализацию, перед массивом пишет длину и т.д.).

Более прямой вариант - расширенная RTTI в D2010 и далее.

Или, возможно, проще пересмотреть структуру данных и вместо дин. массивов использовать статические макс. размера, если это не приведёт к чрезмерному перерасходу памяти.


sniknik   (2011-08-20 11:19:00) [12]

> Я надеялся на что-то вроде этого:
сделай class + методы, и будет почти как ты хочешь... поработаешь за компилятор... ты же знаешь структуру + чего тебе надо. ->
> Ну типа компилятор зная структуру TRec уложит значения куда нужно :)


Inovet   (2011-08-20 11:15:00) [13]

> [18] Sega625   (20.08.11 10:45)
> Она прекрасно заполняется из стандартного файла (.SNG если
> кому интересно) BlocReadами, поэтому добавление новых элементов
> (как то SizeD) крайне нежелательно

Ты что-то недопонимаешь. Или размер или признак конца должен быть.

Ты свой секвенсор что ли пишешь?


Sega625   (2011-08-20 10:45:00) [14]

Я надеялся на что-то вроде этого:


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 Честно говоря не ожидал такого внимания к новичкам, спасибо.


SQLEXPRESS   (2011-08-20 03:20:00) [15]

проще читать


Германн   (2011-08-20 03:03:00) [16]


> SQLEXPRESS   (20.08.11 02:37) [15]

Это решение  уже  представил ИШ.
Чем твоё решение лучше?


SQLEXPRESS   (2011-08-20 02:37:00) [17]

почему? надо передать - передаем
зачем "раскладывать в строку байт"?

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 02:04:00) [18]


> SQLEXPRESS   (20.08.11 01:03) [13]
>
> т.е. Tтип(Pointer(указатель_на_что_надо)) и не надо приводить
> ни к чему
> делаем как удобно
> если понял, конечно
>

Не понял.


SQLEXPRESS   (2011-08-20 01:03:00) [19]

т.е. Tтип(Pointer(указатель_на_что_надо)) и не надо приводить ни к чему
делаем как удобно
если понял, конечно


SQLEXPRESS   (2011-08-20 00:58:00) [20]

да нет же
все проще

по мотиву
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1313045575&n=3


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо