AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi OleVariant über TCP senden

OleVariant über TCP senden

Ein Thema von Sc0rpe · begonnen am 3. Mai 2021 · letzter Beitrag vom 3. Mai 2021
Antwort Antwort
Sc0rpe

Registriert seit: 3. Mai 2021
7 Beiträge
 
Delphi XE6 Professional
 
#1

OleVariant über TCP senden

  Alt 3. Mai 2021, 09:08
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
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: OleVariant über TCP senden

  Alt 3. Mai 2021, 11:36
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;

Geändert von TiGü ( 3. Mai 2021 um 11:39 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.685 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: OleVariant über TCP senden

  Alt 3. Mai 2021, 12:02
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?
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Sc0rpe

Registriert seit: 3. Mai 2021
7 Beiträge
 
Delphi XE6 Professional
 
#4

AW: OleVariant über TCP senden

  Alt 3. Mai 2021, 12:23
So auf dem Trocknenden innerhalb einiger Zeilen geht es ja.
Kommt vielleicht nur nichts (sinnvolles) an? Also eher ein Problem vom Senden und Empfangen.
Ich schätze das liegt daran, dass in diesem Fall ja noch etwaige Pointer stimmen. In der Clientanwendung ist das eben nicht mehr der Fall.

PS: Hast du die Funktionen nochmal hier per Hand geschrieben anstatt kopiert?
Nein, ich habe es kopiert.

In GetOleElementSize() muss es varInt64 anstatt vart64 heißen.
Heißt es doch?!
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: OleVariant über TCP senden

  Alt 3. Mai 2021, 14:10
In GetOleElementSize() muss es varInt64 anstatt vart64 heißen.
Heißt es doch?!
Hahar, lol!
Die Forensoftware löscht da die Buchstaben I und n.
Code:
v a r I n t 6 4 // ohne Leerzeichen denken
wird automatisch zu vart64
EDIT:
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.

Geändert von TiGü ( 3. Mai 2021 um 14:25 Uhr)
  Mit Zitat antworten Zitat
Sc0rpe

Registriert seit: 3. Mai 2021
7 Beiträge
 
Delphi XE6 Professional
 
#6

AW: OleVariant über TCP senden

  Alt 3. Mai 2021, 14:39
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;
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:50 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz