Jump to content
Sign in to follow this  
funkey

Feature request VarGetPtr()

Recommended Posts

funkey

Hello,

i just made a function to get a pointer to the variable variant value. Of course it's very unstable to play with unknown memory areas and I don't know if this works everywhere. I tested on WinXP SP3 x86 and Win7 SP1 x64. What do you think about building in a function like this in AutoIt? I think this could be useful sometimes for example with byref values in DllCalls.

Example1()
ConsoleWrite(@CRLF)
Example2()
ConsoleWrite(@CRLF)
Example3()
;~ ConsoleWrite(@CRLF)
;~ Example4()

Func Example1()
    Local $iStart, $pTest, $tTest
    Local $fTest = 430.2

    $iStart = TimerInit()
    $pTest = _VarGetPtr($fTest)
    ConsoleWrite("Function duration: " & TimerDiff($iStart) & " msec" & @CRLF)

    $tTest = DllStructCreate("double", $pTest)

    ConsoleWrite("Old value: " & $fTest & @CRLF)
    DllStructSetData($tTest, 1, 666.789) ; set new value in variable
    ConsoleWrite("New value: " & $fTest & @CRLF)
EndFunc   ;==>Example1

Func Example2()
    Local $iStart, $pTest, $tTest
    Local $iTest = 415

    $iStart = TimerInit()
    $pTest = _VarGetPtr($iTest)
    ConsoleWrite("Function duration: " & TimerDiff($iStart) & " msec" & @CRLF)

    $tTest = DllStructCreate("int", $pTest)

    ConsoleWrite("Old value: " & $iTest & @CRLF)
    DllStructSetData($tTest, 1, 666) ; set new value in variable
    ConsoleWrite("New value: " & $iTest & @CRLF)
EndFunc   ;==>Example2

Func Example3()
    Local $iStart, $pTest, $tTest
    Local $hTest = Ptr(0x123456FF)

    $iStart = TimerInit()
    $pTest = _VarGetPtr($hTest)
    ConsoleWrite("Function duration: " & TimerDiff($iStart) & " msec" & @CRLF)

    $tTest = DllStructCreate("ptr", $pTest)

    ConsoleWrite("Old value: " & $hTest & @CRLF)
    DllStructSetData($tTest, 1, Ptr(0xBBBBBBBB)) ; set new value in variable
    ConsoleWrite("New value: " & $hTest & @CRLF)
EndFunc   ;==>Example3


Func Example4()
    Local $iStart, $pTest, $tTest

    Local $sTest = "This is a test string"

    $iStart = TimerInit()
    $pTest = _VarGetPtr($sTest)
    ConsoleWrite("Function duration: " & TimerDiff($iStart) & " msec" & @CRLF)

    $tTest = DllStructCreate("wchar[" & StringLen($sTest) + 1 & "]", $pTest)

    ConsoleWrite("Old Struct value: " & DllStructGetData($tTest, 1) & @CRLF)
    ConsoleWrite("Old value: " & $sTest & @CRLF)

    DllStructSetData($tTest, 1, "a", 2) ; set new value in variable

    ConsoleWrite("New Struct value: " & DllStructGetData($tTest, 1) & @CRLF)
    ConsoleWrite("New value: " & $sTest & @CRLF)
EndFunc   ;==>Example4

Func _VarGetPtr(ByRef $var)
    Local $tTest, $pTest, $tTest2, $i = -500, $Save = $var

    Switch VarGetType($var)
        Case "Int32"
            $var = 987654
            $tTest = DllStructCreate("int")
            $pTest = DllStructGetPtr($tTest)

            Do
                $i += 1
                $tTest2 = DllStructCreate("int", $pTest - $i)
            Until DllStructGetData($tTest2, 1) = $var

        Case "Double"
            $var = 1234.5678
            $tTest = DllStructCreate("double")
            $pTest = DllStructGetPtr($tTest)

            Do
                $i += 1
                $tTest2 = DllStructCreate("double", $pTest - $i)
            Until DllStructGetData($tTest2, 1) = $var

        Case "Ptr"

            $var = Ptr(0xFF777777)
            $tTest = DllStructCreate("ptr")
            $pTest = DllStructGetPtr($tTest)

            Do
                $i += 1
                $tTest2 = DllStructCreate("ptr", $pTest - $i)
            Until DllStructGetData($tTest2, 1) = $var

        Case "String"
            Local $tagTemp = "wchar[" & StringLen($var) + 1 & "]"
            $var = "Hello AutoIt"
            $tTest = DllStructCreate($tagTemp)
            $pTest = DllStructGetPtr($tTest)

            Do
                $i += 1
                $tTest2 = DllStructCreate($tagTemp, $pTest - $i)
            Until DllStructGetData($tTest2, 1) = $var

        Case Else
            $var = $Save
            Return 0
    EndSwitch

    $var = $Save

    Return $pTest - $i
EndFunc   ;==>_VarGetPtr

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
Richard Robertson

Pointer to variant isn't useful because the AutoIt variant is likely very different from any other knowable variant. Pointer to specific type makes sense when making dll calls because the dll was already designed for that.

Share this post


Link to post
Share on other sites
funkey

If I could use pointers I could make faster inferfaces to DLLs, for example if I have an array with all integer or double values in it, I could pass a pointer to the first element and get the others by adding the 'sizeof(VARIANT)'. I know this works only with self written DLLs, but could be useful.

Of course more useful would be a function like DLLStructCreateFromAutoitIntegerArray or DLLStructCreateFromAutoitDoubleArray and back again like ArrayCreateFromDLLStruct.

Edit: Another example

#include <WinAPI.au3>

Global $sFile = @ScriptFullPath

Global $hFile = _WinAPI_CreateFile($sFile, 2, 2)
Global $tBuffer = DllStructCreate("char[" & FileGetSize($sFile) + 1 & "]")
Global $iRead = 0
_WinAPI_ReadFileEx($hFile, DllStructGetPtr($tBuffer), FileGetSize($sFile), $iRead)
_WinAPI_CloseHandle($hFile)
ConsoleWrite($iRead & " Bytes read" & @CRLF)


Func _WinAPI_ReadFileEx($hFile, $pBuffer, $iToRead, ByRef $iRead, $pOverlapped = 0)
    Local $aResult = DllCall("kernel32.dll", "bool", "ReadFile", "handle", $hFile, "ptr", $pBuffer, "dword", $iToRead, "ptr", _VarGetPtr($iRead), "ptr", $pOverlapped)
    If @error Then Return SetError(@error, @extended, False)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_ReadFileEx


Func _VarGetPtr(ByRef $var)
    Local $tTest, $pTest, $tTest2, $i = -500, $Save = $var

    Switch VarGetType($var)
        Case "Int32"
            $var = 987654
            $tTest = DllStructCreate("int")
            $pTest = DllStructGetPtr($tTest)

            Do
                $i += 1
                $tTest2 = DllStructCreate("int", $pTest - $i)
            Until DllStructGetData($tTest2, 1) = $var

        Case Else
            $var = $Save
            Return 0
    EndSwitch

    $var = $Save

    Return $pTest - $i
EndFunc   ;==>_VarGetPtr
Edited by funkey

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
Richard Robertson

sizeof(VARIANT) only works if you have a copy of the AutoIt variant, which you don't. That was the point I was trying to make.

Share this post


Link to post
Share on other sites
matwachich

I have another example where VarGetPtr could be usefull for me:

- I have a 2DGameEngine made in a C DLL

- In this DLL, when I create for example a Sprite, it is done with malloc(sizeof(t_sprite))

- In the t_sprite structure, I have an element that can contain user defined data: a simple Integer

- Now, when I use this engin in AutoIt, it would be usefull to "attach" an AutoIt Array to my Sprite by setting the user defined data of the Sprite to the pointer of the AutoIt Array

For the moment, to attach data to my sprites, I allocate some DllStruct and pass the pointer to the user defined data of the sprite

But, I think the problem would be to recover the AutoIt var from a "simple" pointer...

Share this post


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
Sign in to follow this  

×