Форум: "Основная";
Текущий архив: 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