Jump to content

DllStructCreate("SHORT") returns a INT


Go to solution Solved by RTFC,

Recommended Posts

I want to get hex string of a value, that's why I tried DllStructCreate()

The defined short should have been 2 bytes, but a 4-byte int type was returned.

The defined float should have been 4 bytes, but an 8-byte double type was returned.

Local $short = DllStructCreate("SHORT a")
Local $int = DllStructCreate("INT a")
Local $float = DllStructCreate("FLOAT a")
Local $double = DllStructCreate("DOUBLE a")

ConsoleWrite("short size: " & BinaryLen($short.a) & " bytes" & @CRLF) ;~ should be 2, got 4
ConsoleWrite("int size: " & BinaryLen($int.a) & " bytes" & @CRLF) ;~ should be 4
ConsoleWrite("float size: " & BinaryLen($float.a) & " bytes" & @CRLF) ;~ should be 4, got 8
ConsoleWrite("double size: " & BinaryLen($double.a) & " bytes" & @CRLF)  ;~ should be 8

$short.a = 1
$int.a = 1
$float.a = 1
$double.a = 1

ConsoleWrite("short value: " & $short.a & @CRLF)
ConsoleWrite("int value: " & $int.a & @CRLF)
ConsoleWrite("float value: " & $float.a & @CRLF)
ConsoleWrite("double value: " & $double.a & @CRLF)

ConsoleWrite("short Hex: 0x" & Hex($short.a) & @CRLF) ;~ should be 0x0001
ConsoleWrite("int Hex: 0x" & Hex($int.a) & @CRLF) ;~ should be 0x00000001
ConsoleWrite("float Hex: 0x" & Hex($float.a) & @CRLF) ;~ should be 0x3f800000
ConsoleWrite("double Hex: 0x" & Hex($double.a) & @CRLF) ;~ should be 0x3ff0000000000000

I'm using Autoit v3.3.16.1.

What's going on? What did I do wrong?

Link to comment
Share on other sites

  • Solution

There are two separate issues here, 1. struct element retrieval and 2. Hex representation.

ad 1. struct dot notation won't tell you this, but if you check the help page for DllStructGetData, you'll see:

Quote

When the element is char or char[n], wchar or wchar[n] the data returned is always a String(),
when the element is byte[n] and index is omitted the data returned is a binary type,
otherwise it always returns the best fit AutoIt datatype corresponding to the type of the individual element (e.g. byte returns Int32, float returns Double).

ad 2. Reading up on the Hex function in the Help, you'll find:

Quote

Omitting the second parameter (length) or using the keyword Default results in automatic sizing of the output; 8-characters display for numbers that can fit in that and 16-characters display for others.

Link to comment
Share on other sites

On a side note, when using structures (especially at the beginning or your learning), you should always check their integrity by showing the content of the structures with _WinAPI_DisplayStruct function.  When creating more complex structures, alignement can, without notice, include some paddings that you may want or not.  Just so you are aware of this...

Link to comment
Share on other sites

Thank you Nine, _WinAPI_DisplayStruct() clearly tells me that those SHORT and FLOAT are saved correctly in memory.

And thank you RTFC, these docs really helped me, I changed my code as below, and it works.

Local $short = DllStructCreate("SHORT a")
Local $int = DllStructCreate("INT a")
Local $float = DllStructCreate("FLOAT a")
Local $double = DllStructCreate("DOUBLE a")

; share memory
Local $byte_2_for_short = DllStructCreate("BYTE[2]", DllStructGetPtr($short))
Local $byte_4_for_int = DllStructCreate("BYTE[4]", DllStructGetPtr($int))
Local $byte_4_for_float = DllStructCreate("BYTE[4]", DllStructGetPtr($float))
Local $byte_8_for_double = DllStructCreate("BYTE[8]", DllStructGetPtr($double))

ConsoleWrite("short size: " & DllStructGetSize($short) & " bytes" & @CRLF) ;~ should be 2
ConsoleWrite("int size: " & DllStructGetSize($int) & " bytes" & @CRLF) ;~ should be 4
ConsoleWrite("float size: " & DllStructGetSize($float) & " bytes" & @CRLF) ;~ should be 4
ConsoleWrite("double size: " & DllStructGetSize($double) & " bytes" & @CRLF) ;~ should be 8

$short.a = 1
$int.a = 1
$float.a = 1
$double.a = 1

; returns binary type values now. They are in little-endian style on my PC, but it won't be big problem for me.

Local $hexStringForShort = DllStructGetData($byte_2_for_short, 1)
Local $hexStringForInt = DllStructGetData($byte_4_for_int, 1)
Local $hexStringForFloat = DllStructGetData($byte_4_for_float, 1)
Local $hexStringForDouble = DllStructGetData($byte_8_for_double, 1)

ConsoleWrite("short Hex: 0x" & Hex($hexStringForShort) & @CRLF) ;~ should be 0x0001
ConsoleWrite("int Hex: 0x" & Hex($hexStringForInt) & @CRLF) ;~ should be 0x00000001
ConsoleWrite("float Hex: 0x" & Hex($hexStringForFloat) & @CRLF) ;~ should be 0x3f800000
ConsoleWrite("double Hex: 0x" & Hex($hexStringForDouble) & @CRLF) ;~ should be 0x3ff0000000000000

Thank you both again!

Link to comment
Share on other sites

2 hours ago, Sunev_C said:
; returns binary type values now. They are in little-endian style on my PC, but it won't be big problem for me.

You can swap them this way...

ConsoleWrite("short Hex: 0x" & Hex(Number($hexStringForShort)) & @CRLF) ;~ should be 0x0001
ConsoleWrite("int Hex: 0x" & Hex(Number($hexStringForInt)) & @CRLF) ;~ should be 0x00000001
ConsoleWrite("float Hex: 0x" & Hex(Number($hexStringForFloat)) & @CRLF) ;~ should be 0x3f800000
ConsoleWrite("double Hex: 0x" & Hex(Number($hexStringForDouble)) & @CRLF) ;~ should be 0x3ff0000000000000

 

Some guy's script + some other guy's script = my script!

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...