Autor Beitrag
Stephan.Woebbeking
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 97



BeitragVerfasst: Mo 31.05.10 14:11 
Hallo *,

ich habe hier ein Verständnisproblem beim Konvertieren. Von Komponenten zum Netzwerkzugriff bekomme ich Daten im Format TBytes (m.W. gleichbedeutend mit array of Bytes?), möchte zum auswerten diese aber in vorgegebene Strukturen konvertieren. In Delphi 7 hat das alles auch wunderbar funktioniert, aber eine neue Applikation entsteht gleich auf Basis von Delphi 2007, da funktioniert das bekannte System so nicht:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure TReceiver.UDPRead(AData: TBytes);
var
  sStatus: WSM_L_Status_InterfType;
  pStatus: ^WSM_L_Status_InterfType;
  line: String;
  id: Longword;
  buf: array of Byte;
  a: Integer;
begin
  activeCur := True;
  id := AData[ 0 ]+ AData[ 1 ] * 256 + AData[ 2 ] * 256*256 + AData[ 3 ] * 256*256*256;
  line := IntToHex( id, 8 );
  SetLength( buf, Length( AData ) );
  for a := 0 to Length( buf ) do
    buf[ a ] := AData[ a ];
  case id of
      WSM_L_Status_InterfId: begin
        pStatus     := @buf;
        sStatus     := pStatus^;


Die Konvertierung in id funktioniert noch, obwohl ich es früher einfacher über ein PLongWord gemacht habe, da kommt aber nur noch Murks raus. Die Daten in AData und dann auch in buf sind korrekt. WSM_L_Status_InterfType ist ein packed record, und der enthält dann für mich völlig unsinnige Daten. Einfache LSB / MSB Anpassung hilft nicht, das habe ich auch schon probiert. Hat irgendjemand eine Ahnung für mich, wie ich den Inhalt von sStatus korrekt erhalten kann???

Vielen Dank,
Stephan

Falls wichtig, hier die Struktur, die dahinter liegt:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
  // WSM_L_Status
  WSM_L_Status_ValueType = packed record
    ByteSize: LongWord;
    DeviceId: LongWord;
    IPAddrEM: array [ 1..4 ] of Byte;
    IPAddrPC: array [ 1..4 ] of Byte;
    MACAddrEM: array [ 1..6 ] of Byte;
    AccessLocked: Byte;
    AccessLockIP: array [ 1..4 ] of Byte;
    DeviceType: LongWord;
    DeviceFeatures: LongWord;
    FreqMin: LongWord;
    FreqMax: LongWord;
    Mute: Byte;
    DiversA: Byte;
    BatTel: Byte;
    Pilot: Byte;
    Timestamp: LongWord;
    BatTelResult: Byte;
    RFLevelA: Word;
    RFLevelB: Word;
    AfLevel: Byte;
    AfMaxHold: Byte;
    AfPeak: Byte;
    AfEn: Byte;
    ComEn: Byte;
    Clock: Byte;
  end;

  WSM_L_Status_EnableType = packed record
    ByteSize: Byte; // aktiv falls ungleich 0
    DeviceId: Byte; // aktiv falls ungleich 0
    IPAddrEM: Byte; // aktiv falls ungleich 0
    IPAddrPC: Byte; // aktiv falls ungleich 0
    MACAddrEM: Byte; // aktiv falls ungleich 0
    AccessLocked: Byte; // aktiv falls ungleich 0
    AccessLockIP: Byte; // aktiv falls ungleich 0
    DeviceType: Byte; // aktiv falls ungleich 0
    DeviceFeatures: Byte; // aktiv falls ungleich 0
    FreqMin: Byte; // aktiv falls ungleich 0
    FreqMax: Byte; // aktiv falls ungleich 0
    Mute: Byte; // aktiv falls ungleich 0
    DiversA: Byte; // aktiv falls ungleich 0
    BatTel: Byte; // aktiv falls ungleich 0
    Pilot: Byte; // aktiv falls ungleich 0
    Timestamp: Byte; // aktiv falls ungleich 0
    BatTelResult: Byte; // aktiv falls ungleich 0
    RFLevelA: Byte; // aktiv falls ungleich 0
    RFLevelB: Byte; // aktiv falls ungleich 0
    AfLevel: Byte; // aktiv falls ungleich 0
    AfMaxHold: Byte; // aktiv falls ungleich 0
    AfPeak: Byte; // aktiv falls ungleich 0
    AfEn: Byte; // aktiv falls ungleich 0
    ComEn: Byte; // aktiv falls ungleich 0
    Clock: Byte; // aktiv falls ungleich 0
  end;

  WSM_L_Status_InterfType = packed record
    id: Longword; // eindeutige Identifikation
    val: WSM_L_Status_ValueType; // zu uebermittelnde Werte
    enable: WSM_L_Status_EnableType; // Markierung relevanter Werte
  end;


Zuletzt bearbeitet von Stephan.Woebbeking am Di 01.06.10 08:52, insgesamt 1-mal bearbeitet
GuaAck
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 378
Erhaltene Danke: 32

Windows 8.1
Delphi 10.4 Comm. Edition
BeitragVerfasst: Mo 31.05.10 20:02 
Hallo Stephan,

ist den siocher, dass sStatus := pStatus^ arbeitet? Bei offenen ARRAYs (als ohne Grenzen deklariert, dann erst mit setlength die Länge festgelegt) wird durch ":=" nur der Pointer auf das eigentliche Feld kopiert. (M. E. eine sehr verunglückte Definition in PASCAL.)

Da würde ich suchen. Versuch doch z. B. sStatus := COPY(pStatus^);

Gruß
Guenther
Bergmann89
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: Di 01.06.10 00:13 
Hey,

user profile iconStephan.Woebbeking hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
  for a := 0 to Length( buf ) do
    buf[ a ] := AData[ a ];

So überschreibst du Speicher der nicht mehr zu Array gehört. Ein Array geht (wenn mit SetLength erstellt) immer von 0 bis N-1. Also Entwerde du lässt die schleife bis Length(buf)-1 gehen, oder benutzt gleich High(buf), welches dir den größtmöglichen Index zurück gibt.
Weiterhin kann man man den PointerType auch gleich so casten un muss nich den Umweg über eine Variable gehen (es dei denn du brauchst die später noch iwo, was ich jetzt hier nicht sehe):sStatus := pStatus(@buf)^;
Und kannst du dann noch das Record (WSM_L_Status_InterfType) posten?

€: noch ein Typ für die Berechnung von Id. So sollte das auch gehen un da haste nich so viel zu rechnen: id := PInteger(@AData)^;

MfG Bergmann

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
Stephan.Woebbeking Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 97



BeitragVerfasst: Di 01.06.10 09:05 
@GuaAck: Was du vorgeschlagen hast, habe ich ursprünglich so gehabt (in der "alten" Version arbeitet das ohne Probleme), aber nachdem es in Delphi 2007 nicht mehr wollte, habe ich natürlich andere Wege probiert.
Es ist so, dass nach der Zuweisung sStatus := pStatus^ sind die Daten völlig andere, nicht etwa ein Byte verschoben, Nullen angefügt etc, irgendwie scheint ein völlig anderer Speicherbereich verwendet zu werden, aber ich sehe nicht, warum??? Aber ich probiere mal Copy...

@Bergmann89: Ok, das mit dem Array ist ein fairer Hinweis, aber das war 'eh der quick-n-dirty Versuch und gibt grundsätzlich Probleme. Nicht beim Kopieren des Array, sondern beim casten auf die Struktur... Ich habe die Struktur oben noch in den ursprünglichen Post eingefügt. Es handelt sich eben nicht um ein array, sondern um einen packed record, daher bin ich davon ausgegangen, dass das soweit passen müsste?!? Ich benötige die Daten später nicht mehr, nur die Zuweisung mit dem Cast arbeitet bei mir nicht korrekt. Das gilt auch für die id, in der Tat hatte ich das vorher so, wie du geschrieben hast, bekomme aber völlig andere Werte und hab keinen Schimmer warum??? *snief*

Zur Verdeutlichung:

ausblenden Delphi-Quelltext
1:
2:
  id := PInteger(@AData)^;
  id := AData[ 0 ]+ AData[ 1 ] * 256 + AData[ 2 ] * 256*256 + AData[ 3 ] * 256*256*256;


Wenn ich diese beiden Zeilen ausführe... AData wird dabei mit [ 5, 6, 18, 6 ... ] berichtet, hat id nacheinander die Werte 13348136 und dann 101844485...??? Häh??? Selbst wenn ich die Werte Hex/Bin umrechne hilft mir das null weiter. Was ich allerdings weiß ist, der Inhalt von AData ist korrekt und die zweite id stimmt, die erste nicht. Kleinen Versuch habe ich noch durchgeführt: "id := PLongWord(@AData)^;" macht auch keinen Unterschied... Dass ich hier oben mit LSB/MSB Reihenfolge spiele ist klar, hat mich der Lösung aber bisher nicht für fünf Cent näher gebracht... Ich sehe es einfach nicht?

Stephan
Tryer
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 226
Erhaltene Danke: 7



BeitragVerfasst: Di 01.06.10 09:29 
Ich würde sagen AData selber ist nur ein Zeiger auf das Array. @AData ist dann ein Zeiger auf den Zeiger der auf das Array zeigt. Wenn Du @AData dereferenzierst landest Du also an der Stelle wo der Zeiger (die Adresse des Arrays) im Speicher steht, nicht im Array selber. Das bekommst du mit @AData[0].

Grüsse, Dirk
Stephan.Woebbeking Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 97



BeitragVerfasst: Di 01.06.10 10:53 
Wow, das funktioniert tatsächlich... Wer ist denn auf die Idee gekommen, dass @Data etwas anderes ist als @Data[0]...??? Ich bin wohl deutlich stärker in der Java Welt verwurzelt, auf den Trichter wäre ich nie allein gekommen!

Vielen Dank,
Stephan