Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   struct als TBytes nach record? (https://www.delphipraxis.net/102540-struct-als-tbytes-nach-record.html)

Piberg 30. Okt 2007 17:16


struct als TBytes nach record?
 
Hallo Forum!

Nachdem ich einige Threads durchgeschaut habe, konnte ich diesen C++struct

Code:
typedef struct {
  short enable ;
  short side ;
  short angle ;
  short x ;
  short y ;
} pos_t ;

typedef struct {
  char name[16] ;
  short masse;
} obj_t ;

/* und endlich */
typedef struct {
  char pmode ;   /* nimmt Werte eines enum auf z.B. (pm_null, pm_1, pm_2) */
  obj_t figure[2] ;
  pos_t pos[3] ;
  short time ;
} info_t ;
in folgende Delphi-Typen überführen: (Hoffentlich ist es richtig. Bin für jede Bemerkung dankbar.)

Delphi-Quellcode:
type pos_t = packed record
  enable,
  side,
  angle,
  x, y : Smallint ;
end;

type obj_t = packed record
  name : string[16] ;  // oder : array [0..15] of char ???
  masse: Smallint ;
end;

// und endlich
type info_t = packed record
  pmode : (pm_null, pm_1, pm_2) ;
  figure: array [0..1] of obj_t ;
  pos  : array [0..2] of pos_t ;
  time : Smallint ;
end;


Jetzt zum eigentlichen Problem. Und zwar konnecte ich von Delphi aus zu einem Linux-Programm, das mir
das o.g. struct info_t über UDP sendet.
Dieses kann ich dann mit dem UDPRead-Ereignis von Indys idUDPServer empfangen. Die Daten sind dann im
Parameter AData vom Typ TBytes gespeichert.
Ach ja, ich muss noch erwähnen, dass es unterschiedliche structs verschickt werden. Das da Oben, war nur
ein kurzes Beispiel. Was sie nur gemeinsam haben ist pmode, anhand dessen ich unterscheiden kann,
was das nun fürn struct-Typ angekommen ist.

Und nun meine Frage:
Wie kann ich die empfangenen Bytes von AData nach mein record speichern? Ich muss ja auch zuerst
an pmode ran, um feststellen zu können, ob ich in mein info_t record oder ein anders
nehme.

Und bei der Gelegenheit noch ne Frage zur Typenwandlung:
Muss in diesem Fall wirklich ein packed record sein?


Danke im Voraus :-)

DeddyH 30. Okt 2007 17:19

Re: struct als TBytes nach record?
 
Ich würde das packed mal weglassen. AFAIK richten C-Compiler Strukturen auch auf 4 Byte aus, bin aber da nicht ganz sicher.

Apollonius 30. Okt 2007 17:32

Re: struct als TBytes nach record?
 
Du solltest keine Shortstrings verwenden, da in diesen noch ein Längenbyte ist. Also, wie du selbst vorgeschlagen hast, besser ein array[0..15] of char nehmen. Wenn ich mit den Indys Records empfangen habe, habe ich das immer so gemacht: Erstmal TBytes empfangen. TBytes ist ein dynamisches Array, also ein Zeiger auf eine Byte-Folge. Das ganze habe ich in den Zeigertyp des Records gecastet und gerne auch mal mit with umschlossen, also so:
Delphi-Quellcode:
var rec: TMeinRecord; Bytes: TBytes;
begin
IdTCPClient1.ReadBytes(Bytes, SizeOf(TMeinRecord));
rec:=PMeinRecord(Bytes)^;
//oder auch
with PMeinRecord(Bytes)^ do
  begin
  end;
end;
Das ganze ist ungetestet, es kann sein, dass ich die Syntax nicht mehr ganz im Kopf habe.

Christian Seehase 30. Okt 2007 17:33

Re: struct als TBytes nach record?
 
Moin Piberg,

Delphi-Quellcode:
name : string[16] ;  // oder : array [0..15] of char ???
ich plädiere hier für das Oder ;-)

Ein ShortString enthält auf Index 0 noch die Länge, er würde also die Struktur stören.

Ob Du nun packed nehmen solltest, oder sogar eine spezielle $ALIGN-Einstellung benötigst, hängt davon ab, mit welchem Alignment die Strukur compiliert werden soll.

Um die Daten zu übertragen könntest Du einfach einen varianten Record nehmen, der alle möglichen Strukturen enthält.
U.A. auch eines vom Typ TBytes, dass Du dann der Funktion zum Füllen übergeben kannst.

Apollonius 30. Okt 2007 17:39

Re: struct als TBytes nach record?
 
Variante Records sind zwar grundsätzlich eine gute Idee, aber ich bezweifle, dass das mit TBytes funktioniert. In IdGlobal (Indy 10) ist TBytes als array of Byte deklariert, und wie bereits gesagt sind dynamische Arrays Zeiger.

SirThornberry 30. Okt 2007 17:45

Re: struct als TBytes nach record?
 
ich würde einfach einen Pointertyp des Records erstellen und dann darüber zugreifen:
Delphi-Quellcode:
type
  PInfo_t = ^info_t;

[...]

var
  lInfo: PInfo_t;
begin
  lInfo = @TBytesParameter[0];
  //do anything with lInfo^.pmode etc.

Piberg 31. Okt 2007 07:58

Re: struct als TBytes nach record?
 
Hallo Leute.
Erstmal vielen Dank für die raschen Antworten. Es ist nämlich genau das, was ich wissen wollte. :bounce2:
Ich war mir nicht sicher, von welcher Seite ich mich an die empfangenen Bytes ranmachen sollte
und wollte wissen, wie das die anderen, die vielleciht mehr Erfahrung haben, machen würden. :-)

Naja, ich werde noch ausprobieren müssen, welches record (packed oder nicht) ich nehmen werde,
denn leider weiss ich nicht, mit welchen Compiler-Einstellungen, das Gegenprogramm, das unter
Linux läuft compilert wurde. :coder:

Auf jeden Fall grosses Dankeschön an Alle

himitsu 31. Okt 2007 08:16

Re: struct als TBytes nach record?
 
Zitat:

Zitat von Piberg
Naja, ich werde noch ausprobieren müssen, welches record (packed oder nicht) ich nehmen werde

Am Einfachsten erstmal nachsehn wie groß die empfangenen Recorddaten sind.
Wenn ich micht jetzt nich verrechnet hab, dann wäre der Record packed 51 Byte groß
und unpacked demnach eventuell größer.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:19 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