Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.10.24;
Скачать: [xml.tar.bz2];

Вниз

RecordToVariant и обратно   Найти похожие ветки 

 
IceT   (2004-10-11 15:51) [0]

Написал функцию, для перевода любого record в OleVariant.

function RecordToVariant(ARecord: Pointer; ASize: integer): OleVariant;
var
 P: Pointer;
begin
 Result := VarArrayCreate([0, ASize], varByte);
 P := VarArrayLock(Result);
 try
   Move(ARecord^, P^, ASize);
 finally
   VarArrayUnlock(Result);
 end
end;

Но после ее вызова вываливается AV. Причем безконечный ексепшн. Мот кто подскажешь где грабли?


 
Суслик ©   (2004-10-11 15:54) [1]

в записи типы с управляемым временем жизни - строки, дин массивы, интрефейсы и пр.


 
IceT   (2004-10-11 16:21) [2]

>Суслик
А почему если указываешь конктретный record, то все ОК. Т.е.

TDataType = record
 ID: integer;
 IDRef: integer;
 Notice: string;
 Sum: double;
end;

function RecordToVariant(ARecord: TDataType): OleVariant;
var
 P: Pointer;
begin
 Result := VarArrayCreate([0, SizeOf(TDataType)], varByte);
 P := VarArrayLock(Result);
 try
   Move(ARecord, P^, SizeOf(TDataType));
 finally
   VarArrayUnlock(Result);
 end
end;


 
Суслик ©   (2004-10-11 16:23) [3]


> А почему если указываешь конктретный record, то все ОК.
> Т.е.

тебе везет - обе конструкции некорректные.


 
IceT   (2004-10-11 16:33) [4]

Вообще-то это не я придумал, это в киге по COM Эрик Хармона. А в чем некорректность?


 
Суслик ©   (2004-10-11 16:36) [5]


> Вообще-то это не я придумал, это в киге по COM Эрик Хармона

у него вроде другой пример. Уточни номер страницы.

В чем ошибка я тебе в [1] ответил.


 
Суслик ©   (2004-10-11 16:40) [6]

Нашел я пример.

TPartRecord = packed record
  PartNumber: string[10];
end;

жирный кусочек важен.
сравни со своим.


 
IceT   (2004-10-11 16:54) [7]

Спасибо. Но вариант с "неконкретным" record все равно не проходит(см. сабж)


 
Суслик ©   (2004-10-11 17:03) [8]


> Но вариант с "неконкретным

Заладил блин...

Уважаемый, делай следующее:
1. прочти внимательно хелп по long string и short strings. Сделай вывод, чем отличается их реализация.
2. Открой пример Хармона. Внимательнейшим образом его прочти. Обрати внимание на квадтарные скобочки. Сделай вывод о том, к какому типу принадлежит эта строка (хинт - shortstring).
3. Внимательно посмотри на свой код. Заметь, что у тебя нет [] после строк. Сделай вывод о том, к какому типу приналдежал твои строки (хинт - long string)
4. В спомни из пункта 1 в чем разница между дл. и кор. строками. Сделай вывод почему у тебя не работает.

ЗЫ. Может рановато за COM обраться, когда не знаешь особенности низкоуровневой работы с такими базовыми понятиями языка как строки? Без обид, просто хочу, чтобы ты задумался об этом.


 
IceT   (2004-10-11 17:36) [9]

>Суслик
Даже если выкинуть любое упоминание об string, то все равно вываливается. По поводу стрингов - спасибо за заботу, но это все мне известно...


 
Суслик ©   (2004-10-11 17:39) [10]


> но это все мне известно...

сомневаюсь.

Если валится приводи более полный код:
1. RecordToVariant (полностью)
2. VariantToRecord (полностью)
3. Место вызова  RecordToVariant
4. Место вызова VariantToRecord
5. Полное описание TDataType


 
Devel ©   (2004-10-11 17:40) [11]

type
 TTest = packed record
   Field1: Longint;
   Field2: ShortString;
 end;
 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

function RecordToVariant(AValue: Pointer; ASize: Integer): OleVariant;
var
 P: Pointer;
begin
 Result := VarArrayCreate([0, ASize - 1], varByte);
 P := VarArrayLock(Result);
 try
   move(AValue^, P^, ASize);
 finally
   VarArrayUnLock(Result);
 end;
end;

procedure VariantToRecord(AValue: OleVariant; var ARecord);
var
 P: Pointer;
 Len: Integer;
begin
 Len := VarArrayHighBound(AValue, 1) - VarArrayLowBound(AValue, 1) + 1;
 P := VarArrayLock(AValue);
 try
   move(P^, ARecord, Len);
 finally
   VarArrayUnLock(AValue);
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 Test1, Test2: TTest;
 AVariant: OleVariant;
begin
 ZeroMemory(@Test1, SizeOf(Test1));
 ZeroMemory(@Test2, SizeOf(Test2));
 Test1.Field1 := 1;
 Test1.Field2 := "test";
 AVariant := RecordToVariant(@Test1, SizeOf(Test1));
 VariantToRecord(AVariant, Test2);
 ShowMessage("Test2.Field1=" + IntToStr(Test2.Field1) + "Test2.Field2=" +
   Test2.Field2);

end;


 
Erik1 ©   (2004-10-11 18:03) [12]

Какая лажа. Я писал код преобразования record в Variant, причем рабочий код. Так пришлось для каждого record писать саою функцию, конечно ана состояла из одинаковых кусков. Но это намного сложнее чем себе представляет IceT. Даю ОТЛАЖЕНЫЙ пример:
prvOptions = (prvCurrentRow, prvMetaData);
RProvRef = packed record
 Name: ShortString;
 Options: set of prvOptions;
end;
TProv = packed Array of RProvRef;
PBackProv = ^TProv;

procedure DataToVariant(Const pRef: PBackProv; Var VData: OleVariant); overload;
procedure VariantToData(Var VData: OleVariant; Const pRef :PBackProv); overload;

procedure DataToVariant(Const pRef: PBackProv; Var VData: OleVariant);
Var
  ArraySize, RecSize: Word;
  StrLen: Byte;
  PData: PByteArray;
  j, i, SizeMem : Integer;
//    Buf: Array[0..100] of word absolute PData;
begin
 RecSize := SizeOf(pRef^);
 ArraySize := Length(pRef^);
 SizeMem := 0;
 for i := 0 to ArraySize-1 do
   Inc(SizeMem, (SizeOf(pRef^[i].Options)+Length(pRef^[i].Name)+1));
 SizeMem := SizeMem + SizeOf(RecSize) + SizeOf(ArraySize);
//  OutputDebugString(PChar(IntToStr(SizeMem)));

 VData := VarArrayCreate([0, SizeMem], varByte);
 PData := VarArrayLock(VData);
 try
   i := 0;
   MoveREx(@RecSize, PData, i, SizeOf(RecSize));
   MoveREx(@ArraySize, PData, i, SizeOf(ArraySize));
   for j := 0 to ArraySize-1 do
   begin
     StrLen := Length(pRef^[j].Name)+1; //+0 index string size
     MoveREx(@pRef^[j].Name, PData, i, StrLen);
     MoveREx(@pRef^[j].Options, PData, i, SizeOf(pRef^[j].Options));
   end;
 finally
   VarArrayUnLock(VData);
 end;
end;

procedure VariantToData(Var VData: OleVariant; Const pRef :PBackProv);
Var
   ArraySize, RecSize: Word;
   StrLen: Byte;
   PData: PByteArray;
   i, j: Integer;
begin
 PData := VarArrayLock(VData);
 try
   i := 0;
   MoveEx(PData, @RecSize, i, SizeOf(RecSize));
   if RecSize <> SizeOf(pRef^) then
     raise Exception.Create("Error size PRefDataSet in VariantToData");

   MoveEx(PData, @ArraySize, i, SizeOf(ArraySize));
   SetLength(pRef^, ArraySize);
   for j := 0 to ArraySize-1 do
   begin
MoveEx(PData, @StrLen, i, SizeOf(StrLen));
     SetLength(pRef^[j].Name, StrLen);
MoveEx(PData, @pRef^[j].Name[1], i, StrLen);
MoveEx(PData, @pRef^[j].Options, i, SizeOf(pRef^[j].Options));
   end;
 finally
   VarArrayUnLock(VData);
 end;
end;

procedure MoveEx(const P1, P2: PByteArray; var Index: Integer; Size: Integer);
begin
 Move(P1^[Index], P2^, Size);
 Inc(Index, Size);
end;


 
Суслик ©   (2004-10-11 18:08) [13]


>  [12] Erik1 ©   (11.10.04 18:03)


> Какая лажа

силен ты выводы делать.
Все у него нормально за исключенями:
1. юзает длинные строки
2. не приводит кода, как он вызывает recordtovariant


 
Erik1 ©   (2004-10-11 18:42) [14]

Я вижу систематическую ошибку, так что все нармально это слишком сильно сказано. Вобщем небудет работать такой подход, а то знаю сам сначала так написал, но исправился тоже сам!


 
IceT   (2004-10-11 19:37) [15]

>Devel
Спасибо.


 
IceT   (2004-10-11 19:37) [16]

>Devel
Спасибо.


 
Суслик ©   (2004-10-11 19:48) [17]

радостно, что 16-ому посту стал понятен ответ [1].

>Devel
Спасибо! У меня не всегда получается объяснять доходчиво.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2004.10.24;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.03 c
6-1092912367
Эдик
2004-08-19 14:46
2004.10.24
TClientSocket разрыв соединения


14-1097133970
Aleksey V.P.
2004-10-07 11:26
2004.10.24
Глюк или я тормоз?


3-1095938546
Nick-From
2004-09-23 15:22
2004.10.24
TDBComboBox не дает выбирать значения


4-1095648700
mikl2002
2004-09-20 06:51
2004.10.24
Как программно выбрать звуковуху для вывода звука


1-1097235049
Cosinus
2004-10-08 15:30
2004.10.24
StringGrid и пунктир if gdFocused (DrawFocusRect)?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский