Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.10.24;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.042 c
6-1092421868
Junior
2004-08-13 22:31
2004.10.24
TServerSocket в консольном приложении


14-1097055400
Novenkiy
2004-10-06 13:36
2004.10.24
Всё про Excel


14-1095845490
olookin
2004-09-22 13:31
2004.10.24
Прогнозы на 2-й тур Лиги Чемпионов


6-1092112346
r9000
2004-08-10 08:32
2004.10.24
Помогите, пожалуйста с Web-сервером


3-1096319312
Lamer8
2004-09-28 01:08
2004.10.24
Как получить новое значение счётчика