Jump to content

Copy binary data to struct


Go to solution Solved by TheXman,

Recommended Posts

Hello,

I am receving data from a TcpServer. The data itself can be decoded by using a structure, for example:

$tStruct = DllStructCreate("char[12];int[13];byte[5];double[5]")

The length of the received data will match the length of the struct.

Is there an easy way to copy the binary data directly into the structure, so that I don't have to use BinaryMid etc.?

 

Link to comment
Share on other sites

  • Solution
18 hours ago, HurleyShanabarger said:

Is there an easy way to copy the binary data directly into the structure, so that I don't have to use BinaryMid etc.?

If you read the data into a byte buffer struct, there's no need to copy it anywhere.  The data can be accessed by using an accessor struct that points to the memory location of the byte buffer struct.  If you must copy the data, then you can use _WinAPI_CopyStruct() to copy the byte buffer to another byte buffer and then access it using the same technique.

For example:

#include <WinAPIDiag.au3>

example()

Func example()
    Const $tagByteBuffer   = "byte byteBuffer[12];", _
          $tagAccessRecord = "int intVals[3]"

    Local $tByteBuffer   = DllStructCreate($tagByteBuffer), _
          $tAccessRecord = DllStructCreate($tagAccessRecord, DllStructGetPtr($tByteBuffer)); points to byte buffer

    Local $xData = Binary("0xFF000000FFFF0000FFFFFF00") ;3 little-endian ints


    ;Read data into byte buffer
    $tByteBuffer.byteBuffer = $xData

    ;Access & display values using the access record struct
    ConsoleWrite("$xData    = " & $xData & @CRLF & @CRLF)
    ConsoleWrite(StringFormat("intVal(1) = %8i (0x%08X)", $tAccessRecord.intVals(1), $tAccessRecord.intVals(1)) & @CRLF)
    ConsoleWrite(StringFormat("intVal(2) = %8i (0x%08X)", $tAccessRecord.intVals(2), $tAccessRecord.intVals(2)) & @CRLF)
    ConsoleWrite(StringFormat("intVal(3) = %8i (0x%08X)", $tAccessRecord.intVals(3), $tAccessRecord.intVals(3)) & @CRLF)

    ;Display byte buffer and access record struct
    _WinAPI_DisplayStruct($tByteBuffer  , $tagByteBuffer  , "Byte Buffer Struct")
    _WinAPI_DisplayStruct($tAccessRecord, $tagAccessRecord, "Access Record Struct")
EndFunc

Console output:

$xData    = 0xFF000000FFFF0000FFFFFF00

intVal(1) =      255 (0x000000FF)
intVal(2) =    65535 (0x0000FFFF)
intVal(3) = 16777215 (0x00FFFFFF)

 

Edited by TheXman
Link to comment
Share on other sites

Thank you for the solution. I tried it myself using your way in the meantime, but it didn't work.

I started testing

DllCall("MSVCRT.DLL", "ptr:cdecl", "memcpy", "struct*", $tTrg, "struct*", $_lv_tSrc, "uint", DllStructGetSize($_lv_tSrc))

which was also doing the job, but I the other solution is better.

Also thank you for showing me 

_WinAPI_DisplayStruct

was not aware of that solution (acutally had my one version of it).

Link to comment
Share on other sites

Functions already exist to do just that.
Download the UDF "BinaryHelpers.au3" from >>here<< and then you can solve your problem as follows:

#include "BinaryHelpers.au3"

Global $tagStruct = "char[12];int[13];byte[5];double[5]"
Global $bBin = Binary("0x68656C6C6F20776F726C640010270000204E000030750000409C000050C3000060EA00007011010080380100905F0100A0860100B0AD0100C0D40100D0FB0100BBCCDDEEFF000000000000000000F03F000000000000E03F555555555555D53F000000000000D03F9A9999999999C93F")

; convert the binary into a autoit dll-struct
Global $tStruct = _bin_BinToStruct($bBin, $tagStruct)

ConsoleWrite(DllStructGetData($tStruct, 1) & @CRLF)

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...