Hallo liebes Forum,
ich schreibe gerade Client/Server Anwendungen mit TIdTCPServer und TIdTCPClient. Dabei muss auch eine Variable des Typs OleVariant gesendent werden, welche auf der anderen Seite auch entsprechend wieder ankommen muss.
Das ganz machen ich über TMemoryStream. Dafür habe ich die Funktionen
MemStrmToOleVariant (beim Empfangen) und OleVariantToMemStrm (zum Senden) geschrieben. Da im OleVariant ja theorethisch alles mögliche stehen kann, schreibe ich mir einige Sachen in den Memorystream, die ich beim empfangen als erstes wieder auslese. Z.b. ob der OleVariant ein Array is, wieviele Elemente ggf. darin stehen und die Anzahl an Bytes die ich für die Daten auslesen muss. Leider klappt das nicht, wenn der OleVariant ein Array von Strings ist. Nun ist die Frage, wie ich das am besten machen kann. Laut Dokumentation soltle mir VarArrayLock(OleVar) ja den Pointer auf die Daten zurückgeben. Wie ist das aber bei Strings? Dazu konnte ich nichts finden. Der String hat ja keine feste Länge, wie z.B. ein Integer?!
Kann mir jemand helfen?
Code:
function MemStrmToOleVariant(
MemStr: TMemoryStream): OleVariant;
var
Size : LongWord;
ByteArr : PByteArray;
IsArray : WordBool;
oleVarType : Word;
NumBytes : integer;
begin
MemStr.Position := 0;
MemStr.ReadBuffer(olevartype, SizeOf(olevartype));
MemStr.ReadBuffer(IsArray, SizeOf(IsArray));
MemStr.ReadBuffer(Size, Sizeof(Size));
MemStr.ReadBuffer(NumBytes, SizeOf(NumBytes));
Result := VarArrayCreate([0, Size-1], oleVarType);
ByteArr := VarArrayLock(Result);
try
MemStr.ReadBuffer(ByteArr^, NumBytes);
finally
VarArrayUnlock(Result);
end;
end;
Code:
function OleVariantToMemStrm(
OleVar: OleVariant): TMemoryStream;
var
ByteArr : PByteArray;
Size : LongWord;
IsArray : WordBool;
oleVarType : Word;
NumBytes : integer;
begin
Result := TMemoryStream.Create;
try
IsArray := VarIsArray(OleVar);
Size := VarArrayHighBound(OleVar, 1) - VarArrayLowBound(OleVar, 1) + 1;
ByteArr := VarArrayLock(OleVar);
oleVarType := VarType(OleVar) and varTypeMask;
NumBytes := GetOleElementSize(oleVarType);
if oleVarType = varOleStr then
NumBytes := lstrlenW(TVardata(OleVar).VOleStr) * NumBytes;
NumBytes := NumBytes * Size;
try
Result.Position := 0;
Result.WriteBuffer(OleVarType, SizeOf(oleVarType));
Result.WriteBuffer(IsArray, SizeOf(IsArray));
Result.WriteBuffer(Size, SizeOf(Size));
Result.WriteBuffer(NumBytes, SizeOf(NumBytes));
Result.WriteBuffer(ByteArr^, NumBytes);
finally
VarArrayUnlock(OleVar);
end;
except
Result.Free;
Result := nil;
end;
end;
Dazu noch diese kleine Helferfunktion, die nur die entsprechende Größe, je nach Typ liefert.
Code:
function GetOleElementSize(oletype: Word): Integer;
var strln : integer;
begin
case oletype of
varDouble: Exit(SizeOf(Double));
varInt64: Exit(SizeOf(Int64));
varByte: Exit(SizeOf(Byte));
varWord: Exit(SizeOf(Word));
varLongWord: Exit(SizeOf(LongWord));
varInteger: Exit(SizeOf(integer));
varSmallint: Exit(SizeOf(SmallInt));
varShortInt: Exit(SizeOf(shortint));
varOleStr: Exit(SizeOf(WideChar));
end;
end;
Grüße
Sc0rpe