Jump to content

Recommended Posts

I seem to have two modes when using Autoit.  No problems what-so-ever most of the time or being completely baffled over something that seems to be easy.  Luckily, the baffled part only seems happens once every two years or so.

What I am trying to do.  I have a file that includes a vessel name and part of its assigned serial number.  Reduced, this is what I am using:

$whatthe=FileOpen("C:\QUAD Manager Accounts\__ ADVANTAGE\__ ADVANTAGE.128",16)
$testtxt=fileopen("C:\QUAD Manager Accounts\__ ADVANTAGE\__ ADVANTAGE.test",2)

When I run this, it does read return the vessel name (in this case the good ship F/V Advantage) but never the serial number.  I am assuming that I am not parsing the file correctly but I cannot figure out how to do it. 

Link to post
Share on other sites

Since you didn't provide the record layout of the binary data, which would ordinarily be required, the script below makes the following assumptions:

  1. The name of the vessel  is a null-terminated char string, starting at offset 0x00 (0), and is no longer than 32 bytes.
  2. The serial number is a little-endian uint (32-bit unsigned integer), starting at offset 0x20 (32)

If the script doesn't work with other records/files, then you need to supply a record layout or make the necessary modifications yourself.

Finally, this is just one of many ways that it could be done.


#include <Constants.au3>


Func example()
    Local $hFile

    Local $tByteBuffer = DllStructCreate("byte data[128]"), _
          $tRecord     = DllStructCreate("char vessel[32]; uint serialNo", DllStructGetPtr($tByteBuffer))

    ;Open the file
    $hFile = FileOpen("__ ADVANTAGE.128", $FO_BINARY)
    If $hfile = -1 Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, "ERROR", "Unable to open file")

    ;Read the binary data from the file & close the file
    $tByteBuffer.data = FileRead($hfile)

    ;Display fields
    ConsoleWrite("Vessel = " & $tRecord.vessel   & @CRLF)
    ConsoleWrite("Serial = " & $tRecord.serialNo & @CRLF)

Console output:

Vessel = __ ADVANTAGE
Serial = 285



Edited by TheXman
Changed serial number from a word to a uint
Link to post
Share on other sites

@TheXman, your use of DllStructs without any corresponding DllCall is edifying.*

Curious, apart from using them with DllCalls or to sort a binary overlay (as in this case), do you find it useful to create structs just to use as standalone data structures?  Are there any downsides to that?

*Apology to BlackFlag for the off-topic

Code hard, but don’t hard code...

Link to post
Share on other sites

I don't associate DllStructs with DllCalls.  I only associate DllStructs with binary data/records.  If I need to work with well-defined binary data/records, then I usually use DllStructs.  Sometimes I will just parse out the fields with BinaryMid() functions, but I find it cleaner and easier to maintain structs.  At the moment, I can't think of any downsides to using structs to work with binary data.  On the other hand, I can think of at least a couple on downsides to using BinaryMid() instead of DllStructs, which mostly involve having to calculate and manage offsets as well as the additional functions necessary to do some of the data type conversions.

I forgot to mention that I also think of DllStructs if I need to work with data pointers.

Edited by TheXman
Link to post
Share on other sites

Agree with @TheXman, DllStructs are absolutely the way to access and (re)interpret binary data.

However, an important caveat is the alignment of its data members. By default, AutoIt uses 8 bytes with #pragma pack directive, which can produce all manner of unexpected misinterpretations due to undesired/unexpected shifts (note that member type size may change depending on processor architecture, e.g., ptrs and handles in x86 vs x64).

To prevent this, I always explicitly align in any struct definition (simply add "align #;" prior to the first data member definition, with # = number of bytes to align each member on), which serves as a note to self (and others reading the code) and may significantly speed up I/O when dealing with large binary data sets.

Link to post
Share on other sites

@TheXman, @RTFC

What you guys are saying makes sense, thx.  OTOH, I’m not sure I’ve made myself totally clear.

Basically because you are referring to “interpret[ing]” and “well-defined records” etc. And I agree there.

But I am also talking about just for internal variable storage - as a way to compensate for there being no direct support for structs in AutoIt.

tl dr;  

I just want to use them so that I can dot notation in my program - and not necessarily as an interface to some predefined binary record.  Does that make sense?


Code hard, but don’t hard code...

Link to post
Share on other sites
4 hours ago, JockoDundee said:

Does that make sense?

Sure. One way to think of structs is as a single database record with named fields containing a fixed-order, fixed-width combination of desired variable types. Dot notation would be one way of accessing the contents of a specific field (DllStructGet/SetData being another). I guess I was thinking more of (numeric) offset-based access from a pointer to the struct.

Another cool feature of structs is that any part (or the entire struct) can be remapped (by parsing the 2nd, optional ptr parameter (obtained with DllStructGetPtr) to a second DllStructCreate call) using a different struct definition, which can for example be used to achieve the equivalent of reinterpret_cast<new type> in C++.

Edited by RTFC
Link to post
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
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Create New...