Why no Local declare generates a wrong result?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Archimede
Posts: 464
Joined: 25 Nov 2021, 09:49
Location: Switzerland / Italy

Why no Local declare generates a wrong result?

Post by Archimede » 18 Aug 2022, 04:23

Hallo.
I have this UDF function, that seem works well:

Code: Select all

AHKHID_GetInputInfo(InputHandle, Flag) {
    Static uRawInput, iLastHandle := 0

    ;Check if it's the same handle
    If (InputHandle = iLastHandle) ;We can retrieve the data without having to call again
        Return NumGet(uRawInput, Flag, AHKHID_NumIsShort(Flag) ? (AHKHID_NumIsSigned(Flag) ? "Short" : "UShort") : (AHKHID_NumIsSigned(Flag) ? "Int" : (Flag = 8 ? "Ptr" : "UInt")))
    Else {    ;We need to get a fresh copy

        ;Get raw data size                                           RID_INPUT
        r := DllCall("GetRawInputData", "UInt", InputHandle, "UInt", 0x10000003, "Ptr", 0, "UInt*", iSize, "UInt", 8 + A_PtrSize * 2)
        If (r = -1) Or ErrorLevel {
            ErrorLevel = GetRawInputData call failed.`nReturn value: %r%`nErrorLevel: %ErrorLevel%`nLine: %A_LineNumber%`nLast Error: %A_LastError%
            Return -1
        }

        ;Prep var
        VarSetCapacity(uRawInput, iSize)

        ;Get raw data                                                RID_INPUT
        r := DllCall("GetRawInputData", "UInt", InputHandle, "UInt", 0x10000003, "Ptr", &uRawInput, "UInt*", iSize, "UInt", 8 + A_PtrSize * 2)
        If (r = -1) Or ErrorLevel {
            ErrorLevel = GetRawInputData call failed.`nReturn value: %r%`nErrorLevel: %ErrorLevel%`nLine: %A_LineNumber%`nLast Error: %A_LastError%
            Return -1
        } Else If (r <> iSize) {
            ErrorLevel = GetRawInputData did not return the correct size.`nSize returned: %r%`nSize allocated: %iSize%
            Return -1
        }

        ;Keep handle reference of current uRawInput
        iLastHandle := InputHandle

        ;Retrieve data
        Return NumGet(uRawInput, Flag, AHKHID_NumIsShort(Flag) ? (AHKHID_NumIsSigned(Flag) ? "Short" : "UShort") : (AHKHID_NumIsSigned(Flag) ? "Int" : (Flag = 8 ? "Ptr" : "UInt")))
    }

    Return 0
}
it is very complicate; I downloaded that from this site.
My question is:
why this function call
iquery := AHKHID_GetInputInfo(InputHandle, Flag)
return a wrong value(depending of the flag value; with Flag := 0 the return value is true, with Flag := ( 08 + A_PtrSize * 2 ) | 0x0100 the return value is everytime 1, wrong ), but if I before declare
Local, iquery
the return value is correct?

Thank you very much

just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Why no Local declare generates a wrong result?

Post by just me » 18 Aug 2022, 05:54

Hi,

I cannot see, how the variable iquery could affect the return value of the posted function. The function doesn't use it.

Flag := (08 + A_PtrSize * 2) | 0x0100 queries for the first UShort value in the RAWMOUSE or RAWKEYBOARD structure following the RAWINPUTHEADER structure.

Archimede
Posts: 464
Joined: 25 Nov 2021, 09:49
Location: Switzerland / Italy

Re: Why no Local declare generates a wrong result?

Post by Archimede » 18 Aug 2022, 08:44

Hallo.
Have no you the debugger to see the variables values?
If no, I think you can use Msg... to show the iQuery value.

just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Why no Local declare generates a wrong result?

Post by just me » 19 Aug 2022, 03:23

The code you posted doesn't contain Local iquery. Show your complete code or at least the part calling AHKHID_GetInputInfo(), please.

Archimede
Posts: 464
Joined: 25 Nov 2021, 09:49
Location: Switzerland / Italy

Re: Why no Local declare generates a wrong result?

Post by Archimede » 19 Aug 2022, 03:44

I'm sorry
I no well copied the function; the complete function is:

Code: Select all

AHKHID_GetInputInfo(InputHandle, Flag) {
    Static uRawInput, iLastHandle := 0

    ;Check if it's the same handle
    If (InputHandle = iLastHandle) ;We can retrieve the data without having to call again
        Return NumGet(uRawInput, Flag, AHKHID_NumIsShort(Flag) ? (AHKHID_NumIsSigned(Flag) ? "Short" : "UShort") : (AHKHID_NumIsSigned(Flag) ? "Int" : (Flag = 8 ? "Ptr" : "UInt")))
    Else {    ;We need to get a fresh copy

        ;Get raw data size                                           RID_INPUT
        r := DllCall("GetRawInputData", "UInt", InputHandle, "UInt", 0x10000003, "Ptr", 0, "UInt*", iSize, "UInt", 8 + A_PtrSize * 2)
        If (r = -1) Or ErrorLevel {
            ErrorLevel = GetRawInputData call failed.`nReturn value: %r%`nErrorLevel: %ErrorLevel%`nLine: %A_LineNumber%`nLast Error: %A_LastError%
            Return -1
        }

        ;Prep var
        VarSetCapacity(uRawInput, iSize)

        ;Get raw data                                                RID_INPUT
        r := DllCall("GetRawInputData", "UInt", InputHandle, "UInt", 0x10000003, "Ptr", &uRawInput, "UInt*", iSize, "UInt", 8 + A_PtrSize * 2)
        If (r = -1) Or ErrorLevel {
            ErrorLevel = GetRawInputData call failed.`nReturn value: %r%`nErrorLevel: %ErrorLevel%`nLine: %A_LineNumber%`nLast Error: %A_LastError%
            Return -1
        } Else If (r <> iSize) {
            ErrorLevel = GetRawInputData did not return the correct size.`nSize returned: %r%`nSize allocated: %iSize%
            Return -1
        }

        ;Keep handle reference of current uRawInput
        iLastHandle := InputHandle

        ;Retrieve data
        Return NumGet(uRawInput, Flag, AHKHID_NumIsShort(Flag) ? (AHKHID_NumIsSigned(Flag) ? "Short" : "UShort") : (AHKHID_NumIsSigned(Flag) ? "Int" : (Flag = 8 ? "Ptr" : "UInt")))
    }

    Return 0
}
This is in the AHKHID.ahk file included in the main program:
#Include %A_ScriptDir%\AHKHID.ahk

OnMessage( WM_INPUT, "InputMsg")
.
.
.
InputMsg(wParam, lParam) {
.
.
.
}
My question is:
why this function call, in the InputMsg function
iquery := AHKHID_GetInputInfo(InputHandle, Flag)
return a wrong value(depending of the flag value; with Flag := 0 the return value is true, with Flag := ( 08 + A_PtrSize * 2 ) | 0x0100 the return value is everytime 1, wrong ), but if in the InputMsg function I before declare
Local, iquery
the return value is correct?
I hope, now, to be enough clear.

Thank you very much

just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Why no Local declare generates a wrong result?

Post by just me » 19 Aug 2022, 05:29

Archimede wrote:...; with Flag := 0 the return value is true ...
With Flag := 0 the function will return 0 (RIM_TYPEMOUSE), 1 (RIM_TYPEKEYBOARD), or 2 (RIM_TYPEHID) depending on the device type.

Post the complete function InputMsg(wParam, lParam), please. Variables defined in functions are local by default.

Archimede
Posts: 464
Joined: 25 Nov 2021, 09:49
Location: Switzerland / Italy

Re: Why no Local declare generates a wrong result?

Post by Archimede » 19 Aug 2022, 07:28

I know that the variables defined in functions are local by default: it is for that I no understand the problem...
The complete InputMsg(...) function is:

Code: Select all

InputMsg(wParam, lParam) {
	Local r, iScanCode, iDeviceHandle, sKeyDetected

    r := AHKHID_GetInputInfo(lParam, II_DEVTYPE)
	iScanCode := AHKHID_GetInputInfo( lParam, II_KBD_MAKECODE )
	iDeviceHandle := AHKHID_GetInputInfo( lParam, II_DEVHANDLE )
    sKeyDetected := GetKeyName( Format( "sc{1:-x}", iScanCode ))
}
If I no declare Local... the AHKHID_... functions no returns the right value...

just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Why no Local declare generates a wrong result?

Post by just me » 20 Aug 2022, 03:56

You try to access global variables like II_KBD_MAKECODE within the function without declaring them as global. This should work:

Code: Select all

InputMsg(wParam, lParam) {
	Global II_DEVTYPE, II_KBD_MAKECODE, II_DEVHANDLE
	r := AHKHID_GetInputInfo(lParam, II_DEVTYPE)
	iScanCode := AHKHID_GetInputInfo(lParam, II_KBD_MAKECODE)
	iDeviceHandle := AHKHID_GetInputInfo(lParam, II_DEVHANDLE)
	sKeyDetected := GetKeyName( Format("sc{1:-x}", iScanCode))
}
Global variables ->

Assume-global mode: If a function needs to access or create a large number of global variables, it can be defined to assume that all its variables are global (except its parameters) by making its first line either the word "global" or the declaration of a local variable.

swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Why no Local declare generates a wrong result?

Post by swagfag » 20 Aug 2022, 06:13

all its variables are global (except its parameters) by making its first line either the word "global" or the declaration of a local variable.
1.0.31 - April 8, 2005 wrote:Added the ability to pass parameters and receive return values from functions. Functions also support local variables. In addition, ListVars can show the contents of local variables to help debugging. See functions for details.
did some digging and it seems this had been implemented like this from the outset. weed must have been extra strong in 2005... dont do drugs kids, but above all else, dont do v1

Archimede
Posts: 464
Joined: 25 Nov 2021, 09:49
Location: Switzerland / Italy

Re: Why no Local declare generates a wrong result?

Post by Archimede » 20 Aug 2022, 16:00

Thank you.
Now I can no try it; I will try it.
If the problem is that, why it work declaring as Local the variables?

just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Why no Local declare generates a wrong result?

Post by just me » 21 Aug 2022, 05:37

Archimede wrote:If the problem is that, why it work declaring as Local the variables?
Because all variables not declared as Local are assumed to be Global.

In

Code: Select all

InputMsg(wParam, lParam) {
	...
	iScanCode := AHKHID_GetInputInfo(lParam, II_KBD_MAKECODE)
	...
}
iScanCode as well as II_KBD_MAKECODE are assumed to be local so II_KBD_MAKECODE refers to an empty local variable.

In

Code: Select all

InputMsg(wParam, lParam) {
	...
	Local iScanCode := AHKHID_GetInputInfo(lParam, II_KBD_MAKECODE)
	...
}
iScanCode is explicitely declared as local and therefore II_KBD_MAKECODE is assumed to be global and refers to the global variable.

Archimede
Posts: 464
Joined: 25 Nov 2021, 09:49
Location: Switzerland / Italy

Re: Why no Local declare generates a wrong result?

Post by Archimede » 21 Aug 2022, 18:19

But if
II_KBD_MAKECODE
is externally declared, into all functions it must be automatically detected like Global... or not?

Archimede
Posts: 464
Joined: 25 Nov 2021, 09:49
Location: Switzerland / Italy

Re: Why no Local declare generates a wrong result?

Post by Archimede » 24 Aug 2022, 04:27

:-(
Nobody can answer to my last query?

swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Why no Local declare generates a wrong result?

Post by swagfag » 25 Aug 2022, 04:19

what isnt clear exactly? justme already explained the perfectly in layman's terms and also provided the docs extract to boot. just read it. and if u dont understand it, walk away, then come back and read it again until u do

perhaps ure conflating the v2-exclusive behavior of global variables (super-global doesnt exist in v2), where they are globally accessible for reading (but not writing!)

Archimede
Posts: 464
Joined: 25 Nov 2021, 09:49
Location: Switzerland / Italy

Re: Why no Local declare generates a wrong result?

Post by Archimede » 25 Aug 2022, 14:59

Thank you very much, I understood.
The super-global definition seem be the solution.
😊

Post Reply

Return to “Ask for Help (v1)”