![]() |
OleVariant über TCP senden
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:
Dazu noch diese kleine Helferfunktion, die nur die entsprechende Größe, je nach Typ liefert.
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;
Code:
Grüße
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; Sc0rpe |
AW: OleVariant über TCP senden
So auf dem Trocknenden innerhalb einiger Zeilen geht es ja.
Kommt vielleicht nur nichts (sinnvolles) an? Also eher ein Problem vom Senden und Empfangen. PS: Hast du die Funktionen nochmal hier per Hand geschrieben anstatt kopiert? In GetOleElementSize() muss es varInt64 anstatt vart64 heißen.
Delphi-Quellcode:
procedure TForm3.Button1Click(Sender: TObject);
var stream: TMemoryStream; MyVariant, MyVariant2: OleVariant; MyStrings, MyStrings2: TArray<string>; begin MyStrings := MyStrings + ['Hello World, was geht?', 'Alles frisch auf dem Tisch?', 'Huhu, Tifi!']; MyVariant := MyStrings; stream := OleVariantToMemStrm(MyVariant); MyVariant2 := MemStrmToOleVariant(stream); stream.Free; MyStrings2 := MyVariant2; ShowMessage(MyStrings2[2]); end; |
AW: OleVariant über TCP senden
Oder den (Ole)Variant vor dem senden in ein Record verfrachten, nötige Informationen mitgeben, beim Empfänger wieder in ein (Ole)Variant casten lassen?
|
AW: OleVariant über TCP senden
Zitat:
Zitat:
Zitat:
|
AW: OleVariant über TCP senden
Zitat:
Die Forensoftware löscht da die Buchstaben I und n.
Code:
EDIT:
v a r I n t 6 4 // ohne Leerzeichen denken
wird automatisch zu vart64 Doch nicht, dass ist nur bei mir im Google Chrome komisch. Per Microsoft Edge ist es vernünftig?! Hä? Muss ich mal näher untersuchen. |
AW: OleVariant über TCP senden
Okay der aktuelle versuch sieht nun so aus, dass ich mir über TVarData(OleVar).VArray^.Data den Pointer auf die Daten hole. Das scheint mir ein array of PWideString zu sein. Darüber iteriere ich nun und schreibe zuvor die Länge des Strings in den Memorystream. Das ganze läuft soweit auch fehlerfrei durch, nur bekomme ich beim Empfangen immer nur leere Strings in zu lesen. Was mache ich denn falsch?
Code:
function GetOleElementSize(oletype: Word): 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;
Code:
function MemStrmToOleVariant(
MemStr: TMemoryStream): OleVariant; var ArrSize : LongWord; ByteArr : PByteArray; OleData : array of PWideString; IsArray : WordBool; oleVarType : Word; NumBytes, I, StrLength : integer; begin MemStr.Position := 0; MemStr.ReadBuffer(olevartype, SizeOf(olevartype)); MemStr.ReadBuffer(IsArray, SizeOf(IsArray)); MemStr.ReadBuffer(ArrSize, Sizeof(ArrSize)); MemStr.ReadBuffer(NumBytes, SizeOf(NumBytes)); Result := VarArrayCreate([0, ArrSize-1], oleVarType); ByteArr := VarArrayLock(Result); OleData := TVarData(Result).VArray^.Data; SetLength(OleData, ArrSize); try if oleVarType = varOleStr then begin for I := 0 to ArrSize-1 do begin MemStr.ReadBuffer(StrLength, SizeOf(StrLength)); OleData[I] := AllocMem(StrLength * NumBytes); SetLength(OleData[i]^, StrLength); MemStr.ReadBuffer(OleData[I]^, StrLength * NumBytes); end; end else MemStr.ReadBuffer(ByteArr^, NumBytes); finally VarArrayUnlock(Result); end; end;
Code:
function OleVariantToMemStrm(
OleVar: OleVariant): TMemoryStream; var ByteArr : PByteArray; ArrSize : LongWord; IsArray : WordBool; oleVarType : Word; NumBytes : integer; I, StrLength : integer; S : PWideString; begin Result := TMemoryStream.Create; try IsArray := VarIsArray(OleVar); ArrSize := VarArrayHighBound(OleVar, 1) - VarArrayLowBound(OleVar, 1) + 1; ByteArr := VarArrayLock(OleVar); oleVarType := VarType(OleVar) and varTypeMask; NumBytes := GetOleElementSize(oleVarType); // Bytes per Element / in case of string bytes per char if oleVarType = varOleStr then begin ByteArr := TVarData(OleVar).VArray^.Data; end else NumBytes := NumBytes * ArrSize; try Result.Position := 0; Result.WriteBuffer(OleVarType, SizeOf(oleVarType)); Result.WriteBuffer(IsArray, SizeOf(IsArray)); Result.WriteBuffer(ArrSize, SizeOf(ArrSize)); Result.WriteBuffer(NumBytes, SizeOf(NumBytes)); if oleVarType = varOleStr then begin S := PWideString(ByteArr); for I := 0 to ArrSize-1 do begin StrLength := Length(S^); Result.WriteBuffer(StrLength, SizeOf(StrLength)); Result.WriteBuffer(S^, NumBytes * StrLength); // schreibe den String Inc(S); end; end else Result.WriteBuffer(ByteArr^, NumBytes); finally if IsArray then VarArrayUnlock(OleVar); end; except Result.Free; Result := nil; end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:12 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz