Frage zu Struct

  • Hallo Zusammen,

    ich habe ein Verständnisproblem mit dem Befüllen einer Structur. Ich befülle einmal die Structur als Structur und einmal in einem Rutsch als Byte-Array. Doch leider werden hier die Bytes gedreht und ich weiß nicht warum.

    Also speziell meine ich den Unterschied zwischen dem Befüllen einer kompletten Structur in einem String und meiner TestStructur mit 2 einzelnen SetData. Da sind die Bytes gedreht. ?(

    Hier mein Testcode mit Ausgaben in die Console.

    Spoiler anzeigen
    [autoit]


    Opt("MustDeclareVars", 1)

    [/autoit] [autoit][/autoit] [autoit]

    ; Struktur definieren
    Global Const $MyStruct = _ ; 16 Byte in der Summe
    "short Sequenz1;" & _ ; 2 Byte
    "byte Part1A;" & _ ; 1 Byte
    "byte Part1B;" & _ ; 1 Byte
    "uint Address1;" & _ ; 4 Byte
    "short Sequenz2;" & _ ; 2 Byte
    "byte Part2A;" & _ ; 1 Byte
    "byte Part2B;" & _; 1 Byte
    "uint Address2;" ; 4 Byte

    [/autoit] [autoit][/autoit] [autoit]

    ; Angenommene Daten die vom Router zurückkommen
    ; In Hex: 00 01, 1a, 1b, 11 22 33 44, 00 02, 2a, 2b, 55 66 77 88
    Local $BinaryDataFromUDP = "0x00011a1b1122334400022a2b55667788" ; 16 Byte
    Ausgabe("$BinaryDataFromUDP", $BinaryDataFromUDP) ; Testausgabe

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #Region --- UDP-Daten ---
    ; Datensatz (als Struktur)
    Global $UDPStruct = DllStructCreate($MyStruct)

    [/autoit] [autoit][/autoit] [autoit]

    ; Datensatz (als Byte-Ansammlung)
    Global $UDPBinStruct = DllStructCreate("byte[" & DllStructGetSize($UDPStruct) & "]", DllStructGetPtr($UDPStruct))

    [/autoit] [autoit][/autoit] [autoit]

    ; Daten setzen
    DllStructSetData($UDPBinStruct, 1, $BinaryDataFromUDP)

    [/autoit] [autoit][/autoit] [autoit]

    ; Ausgabe in Dezimal
    StructAusgabeDec("$UDPStruct", $UDPStruct)
    ; Ausgabe in Hex
    StructAusgabeHex("$UDPStruct", $UDPStruct)
    #EndRegion --- UDP-Daten ---

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #Region --- Meine Test-Daten ---
    ; Datensatz (als Struktur)
    Global $TestStruct = DllStructCreate($MyStruct)

    [/autoit] [autoit][/autoit] [autoit]

    ; Testweise etwas setzen
    DllStructSetData($TestStruct, "Sequenz1", "0x0001") ; 2 Byte, wie oben in $BinaryDataFromUDP
    DllStructSetData($TestStruct, "Address1", "0x11223344") ; 4 Byte, wie oben in $BinaryDataFromUDP

    [/autoit] [autoit][/autoit] [autoit]

    ; Datensatz (als Byte-Ansammlung)
    Global $TestBinStruct = DllStructCreate("byte[" & DllStructGetSize($TestStruct) & "]", DllStructGetPtr($TestStruct))
    Ausgabe("$TestBinStruct", DllStructGetData($TestBinStruct, 1)) ; Testausgabe

    [/autoit] [autoit][/autoit] [autoit]

    ; Ausgabe in Dezimal
    StructAusgabeDec("$TestStruct", $TestStruct)
    ; Ausgabe in Hex
    StructAusgabeHex("$TestStruct", $TestStruct)
    #EndRegion --- Meine Test-Daten ---

    [/autoit] [autoit][/autoit] [autoit]

    Ausgabe("", @CRLF & @CRLF)
    Exit

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #Region --- Funktionen ---

    [/autoit] [autoit][/autoit] [autoit]

    ; Funktion, die MyStruct in Dec ausgibt
    Func StructAusgabeDec($name, $struct)
    Local $msg = "Struct Size: " & DllStructGetSize($struct) & @CRLF & _
    "Struct pointer: " & DllStructGetPtr($struct) & @CRLF & _
    "Data:" & @CRLF & _
    DllStructGetData($struct, "Sequenz1") & @CRLF & _
    DllStructGetData($struct, "Part1A") & @CRLF & _
    DllStructGetData($struct, "Part1B") & @CRLF & _
    DllStructGetData($struct, "Address1") & @CRLF & _
    DllStructGetData($struct, "Sequenz2") & @CRLF & _
    DllStructGetData($struct, "Part2A") & @CRLF & _
    DllStructGetData($struct, "Part2B") & @CRLF & _
    DllStructGetData($struct, "Address2")

    [/autoit] [autoit][/autoit] [autoit]

    Ausgabe('Struct "' & $name & '" in Dec', $msg)
    EndFunc ;==>StructAusgabeDec

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; Funktion, die MyStruct in Hex ausgibt
    Func StructAusgabeHex($name, $struct)
    Local $msg = "Struct Size: " & DllStructGetSize($struct) & @CRLF & _
    "Struct pointer: " & DllStructGetPtr($struct) & @CRLF & _
    "Data:" & @CRLF & _
    Hex(DllStructGetData($struct, "Sequenz1")) & @CRLF & _ ; LowByte/HighByte? -> Byte sind gedreht
    Hex(DllStructGetData($struct, "Part1A")) & @CRLF & _
    Hex(DllStructGetData($struct, "Part1B")) & @CRLF & _
    Hex(DllStructGetData($struct, "Address1")) & @CRLF & _ ; Little Endian? -> Reihenfolge rückwärts
    Hex(DllStructGetData($struct, "Sequenz2")) & @CRLF & _
    Hex(DllStructGetData($struct, "Part2A")) & @CRLF & _
    Hex(DllStructGetData($struct, "Part2B")) & @CRLF & _
    Hex(DllStructGetData($struct, "Address2"))

    [/autoit] [autoit][/autoit] [autoit]

    Ausgabe('Struct "' & $name & '" in Hex', $msg)
    EndFunc ;==>StructAusgabeHex

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; Funktion, die einfach eine Ausgabe in die Console macht (mit Trennlinie und Überschrift)
    Func Ausgabe($was = "", $Inhalt = "")
    ; Trennlinie
    ConsoleWrite("_______________________________________________________________________________" & @CRLF)
    ; Was
    If $was <> "" Then ConsoleWrite("---- " & $was & " -----" & @CRLF)
    ; Inhalt
    ConsoleWrite($Inhalt & @CRLF)
    EndFunc ;==>Ausgabe

    [/autoit] [autoit][/autoit] [autoit]

    #EndRegion --- Funktionen ---

    [/autoit]

    Und wenn das so ist, wie das ist, mit welchen Funktionen kann ich am schnellsten den uint und den short "drehen"?

    Besten Dank und weiterhin happy computing!
    R@iner

  • Windows verwendet Lillte Endian als Byte-Reihenfolge. Das heißt, die Bytes sind umgedreht, wenn man Binäre Daten in Zahlen umwandelt.

    Und aus welchem Grund willst du die Reihenfolge denn verändern?

  • Hallo Andy,

    ich will die Reihenfolge nicht verändern, aber ein Vergleich von zwei Strukturen funktioniert weben nicht, weil in der der eingelesenen Structur eben alle Bytes andersrum drin stehen. Wie kann ich denn dann die Bytes einer Structur am besten so hin drehen, daß ich die Inhalte vergleichen kann?

    Happy computing!
    R@iner

  • Wie willst du denn vergleichen? Du musst nur darauf aufpassen:
    $var = "0x123456" ist ein String.
    Wird der String einer binären Variable in einer DLLStruct uigewiesen, wird dazu Binary($var) ausgeführt.
    Wird dagegen einer Integer-Variablen der String zugewiesen, wird Number($var) ausgeführt. Number nimmt Big Endian als Ordnung an, da das Hexadezimalsystem so geschrieben wird.
    Um die Byte-Ordnung von Zahlen zu vertauschen, kannst du auf Windows diese Funktionen verwenden:

    [autoit]

    ; Windows systemem sind immer little endian
    ; Network byte Order ist Big Endian
    ; Daher kann man ntohs, ntohl, htonl und htons zur Konvertierung verwenden

    [/autoit][autoit][/autoit][autoit]

    Func _RBO_Long($longVal, $Unsigned=False)
    ; Reverse byte Order long (4 bytes)
    ; Prog@ndy
    Local $type = "long"
    If $Unsigned=True Then $type="ulong"
    Local $aResult = DllCall("Ws2_32.dll", $type, "ntohl", $type, $longVal)
    If @error Then Return SetError(1,0,$longVal)
    Return $aResult[0]
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    Func _RBO_Short($longVal, $Unsigned=False)
    ; Reverse byte Order short ( 2 bytes)
    ; Prog@ndy
    Local $type = "short"
    If $Unsigned=True Then $type="ushort"
    Local $aResult = DllCall("Ws2_32.dll", $type, "ntohs", $type, $longVal)
    If @error Then Return SetError(1,0,$longVal)
    Return $aResult[0]
    EndFunc

    [/autoit]