Jump to content

Static & ByRef


Recommended Posts

Hey M23.

Would you mind telling me in your words, what the OP is after?

Because I still don't know :(

EDIT:

I've a sneaky feeling that whatever it is the OP wants, might better be achieved using beta, with its function in variable syntax.

Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

  • Replies 52
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

  • Moderators

JohnOne,

The basic problem as I understand it is how to update a Local variable from another function which is not being called directly by the original function in which the variable is located. Given that Local variables are not modifiable unless passed ByRef this would seem to be impossible. The short psuedo-code I posted at #14 shows the desired functionality.

As we showed, you can do it by using structs - but the overhead is even worse than using a Global variable, which the OP does not want to do in view of the desired "cut-and-paste" modularity of the function. Personally I feel he is asking too much of AutoIt - but there are some excellent coders here who can work apparent miracles so there is always hope. ;)

Any clearer?

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Still none the wiser, just cannot get which function this variable needs to be retained in.

AFAIK this does the same as #17

Main()

Func Main()
    Local $initialA = 3, $b = 0
    Local $Retain_This_Value = $initialA
    test($initialA, True)
    test($b)
    ConsoleWrite("At the end, $a = " & $initialA & @LF)
EndFunc   ;==>_Main


Func test(ByRef $pointerToResultVar, $fFlag = False)
    Static $staticPointerToResultVar
    If $fFlag Then
        $staticPointerToResultVar = $pointerToResultVar
    EndIf
    Local $oldA = $staticPointerToResultVar
    ConsoleWrite($oldA & @LF)
EndFunc   ;==>_test
Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

@Lars

This is basicly a good idea but, the example misses to show, that the 2. call comes from another fcn which itself cannot reach $a

@JohnOne

what is the ".. function in variable syntax." ?

The difference to post #17 is, that fcn test can manipulate $a in the workspace of fcn main while in the example you cited this is not possible. $a is 3 there and stays 3.

But the detour with the dll struct is ...well not very easy to use. The roleplay is:

Caller1: "Hey Fcn test do something for me and store it in the variable i provide to you ( byRef )"

Caller2: "Hey Fcn test do something else an store it the results in the variable you received from Caller1 to which I got no  access

Edited by Bluesmaster

My UDF: [topic='156155']_shellExecuteHidden[/topic]

Link to comment
Share on other sites

Main()

Func Main()

   Local $initialA = 3, $b = 0

   $a = DllStructCreate( "int var1" )                       ; [ 1 ]  $a is the variable that "test" should get access to
   DllStructSetData( $a , "var1", $initialA )

   test( DllStructGetPtr($a) , True )                       ; [ 2 ]  now we give the pointer of $a to "test" so that it can access it
   test( $b )


   ConsoleWrite("At the end, $a = " &  DllStructGetData( $a , "var1" ) & @LF )


EndFunc



Func test( $pointerToResultVar , $fFlag = False )

    Static $staticPointerToResultVar

    If $fFlag Then
        $staticPointerToResultVar = $pointerToResultVar     ; [ 3 ]  here the access to $a is preserved for later calls
    EndIf


    Local $a
    $a = DllStructCreate( "int var1" , $staticPointerToResultVar )  
    $oldA = DllStructGetData( $a , "var1" )

    ConsoleWrite( $oldA & @LF )

    DllStructSetData( $a , "var1" , $oldA  + 1 )           ; [ 4 ] and finally we can directly set $a without the need of "byRef"

EndFunc   ;==>test

...well I feel I have explained it now so many times I am a bit confused. Is the thread tite so bad chosen?

"Static + ByRef"  >  if you try to maintain the access you get by "byRef" through a Static variable for the next call of the function (without this "byRef") then this is not possible?

When assiging to a static variable you do not assign the access ( c++ pointer behavior ) but a copy of the variable. Thats bad for my  purpose, and I asket for solutions. What is the confusing point?

Edited by Bluesmaster

My UDF: [topic='156155']_shellExecuteHidden[/topic]

Link to comment
Share on other sites

Nope, still not sure I'm getting it, I'm sorry if I'm frustrating you but rest assured I'm just as frustrated trying to figure it out.

Is this correct.

You want a function, anywhere in your script to be able to access and manipulate a variable, without having a global variable anywhere in your script?

If so, what about and environment variable, that any good?

EnvSet()

EnvGet()

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

Sorry for sounding frustrated, I mean you spend your time for me! Thank you very much! The discussion is just a bit repetitive to the one I had with melba.

I do not want global variables because:

1. they can cause conflicts ( so good so known )

2. its not a single script problem, the function must be modular, > who ever calls it must get its individual results ( but without waiting for the fcn )

EnvSet() is just the same as a global variable but with some disadvantages ( slower and you have to refresh the enviroment, just not the purpose of EnvSet() )

Now dont get me wrong, I dont want to overstretch autoit. I just saw it has a pointer-behavior ( "byRef" ) build in which not every language has.

But the pointer is lost when the fcn leaves ( as the whole workspace is by definition execpt for Static variables ). So I would need to give the access with "byRef" again on the second call.

And here is the pity:

The second call comes from another caller ( a timer event ) which does not have the access to the variable anymore....

So I had the choise: developing a costly workaround   <    or   >  asking the experts if static  + byRef is possible    and it ended up in a  costly discussion ^^ which is ok as I ( and others ) can learn something

best regards

Blues

Edited by Bluesmaster

My UDF: [topic='156155']_shellExecuteHidden[/topic]

Link to comment
Share on other sites

  • Moderators

Bluesmaster,

No need to apologise for being frustrated - we quite understand. As I said to JohnOne earlier, I fear you are pushing well beyond the boundaries of a relatively simple language like AutoIt. Hence your difficulties in getting us simple folk to even understand the problem you wish to solve. :(

I have kept an eye on the thread this afternoon and some of the very best AutoIt coders have looked in - the fact that they have not posted makes me think that there is no solution. Although now I have said that someone will no doubt produce one in the next post! :D

However, after some more thought I will take issue with your dislike of Global variables. Why not use the API approach that so many of us use in our UDFs? Use a Global variable but hide it within an include like this:

<snip> See better example below

How does that look? Still modular - except it is an include file not a single function. ;)

M23

Edited by Melba23
Code removed

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Interesting thought M23.

Working with that Idea, our beloved AutoIt3 allows Us to do this.

#AutoIt3Wrapper_Run_AU3Check=n

_Main()

Func _Main()
    Local $initialA = 3, $b = 0
    _Test($initialA)
    _Test($b)
    _Test($b)
    ConsoleWrite("> " & $initialA & @LF)
EndFunc   ;==>_Main


Func _Test(ByRef $PassedArg)
    Static $Called = 0
    If Not $Called Then
        Global $TheVar = $PassedArg
        $Called = 1
    EndIf
    ConsoleWrite($TheVar & @LF)
    $TheVar += 1
    $PassedArg = $TheVar + 1
EndFunc   ;==>_test

Or something similar.

So although it's there, the caller does not have to create a global.

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

  • Moderators

Hi,

After a good night's sleep I have developed a better example of the concept:

#include <Timers.au3>

; This is an include file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Global $g_TheVariable

Func _Set_Var($vVar)
    $g_TheVariable = $vVar
EndFunc

Func _Get_Var()
    Return $g_TheVariable
EndFunc

Func _Func_Include($vW, $vX, $vY, $vZ)

    If IsString($vW) Then
        $g_TheVariable = $vY
    Else
        $iSec = @SEC
        ConsoleWrite("Timer fired at " & $iSec & @CRLF)
        $g_TheVariable = $iSec
        _Set_Var($iSec)
        ConsoleWrite("+Setting Global to: " & $iSec & @CRLF)
    EndIf

EndFunc

; End of include file ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

HotKeySet("{ESC}", "On_Exit")

While 1
    Func_1()
    Sleep(5000)
WEnd


Func Func_1($fKill = False)

    Static $hGUI = 0

    ; Check for timer kill
    If $fKill Then
        _Timer_KillAllTimers($hGUI)
        Return
    EndIf

    If $hGUI Then
        ; What do we have in the Global?
        ConsoleWrite("!Reading from Global: " & _Get_Var() & @CRLF)
    Else
        ; Initiate the whole thing
        ConsoleWrite("Initiating" & @CRLF)
        ; Create GUI
        $hGUI = GUICreate("Just for the timer")
        ; Set timer
        _Timer_SetTimer($hGUI, 2000, "_Func_Include", -1)
        ; Set default value
        _Set_Var(9999)
    EndIf

EndFunc

Func On_Exit()
    ; Kill timer
    Func_1(True)
    ; Exit
    Exit
EndFunc
That is more like Bluesmaster wanted originally. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

@JohnOne

This seems to be a brilliant solution. Unfortunately I discovered a  weakness: If you add another _Test( $b )-Call then $initialA doesnt increase anymore.

The example in this state is based on an illusion, where $initialA gets increased by 2 at once. The global variable is a  copy and not an access token, similar to the static approach.

I would really like to rescue that idea because its so fantastic simple.

@M23

I need some time to understand that concept, I will write back later. Thank you.

 

Blues

Edited by Bluesmaster

My UDF: [topic='156155']_shellExecuteHidden[/topic]

Link to comment
Share on other sites

@JohnOne

This seems to be a brilliant solution. Unfortunately I discovered a  weakness: If you add another _Test( $b )-Call then $initialA doesnt increase anymore.

The example in this state is based on an illusion, where $initialA gets increased by 2 at once. The global variable is a  copy and not an access token, similar to the static approach.

I would really like to rescue that idea because its so fantastic simple.

@M23

I need some time to understand that concept, I will write back later. Thank you.

 

Blues

That's weird that, and at first glance it seems to be a bug, only incrementing a few.

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

Ok, I think I understood. The function ensures, that the global variable is not declared elsewhere and causing conflicts.

This is an interesting approach, that I could need in the future. However, the conflict-argument is not so important as it can be dam by using prefixes and so on.

More important to me was the fact that global variables are simply against the nature of functions, especialy modular, reusable functions.

Functions have input and output. Thats it. If one of the input is a access to a variable of the caller thats fine, but I have never seen a UDF telling

me: "If you use this function you can get your results from the global variable <foo>"

As you said, this is possibly a bit to much for a handy scripting language. If I reflect it properly, what I want is the function to be an object in the sense of object oriented programming.

I call my function and expect it to store individual results just as an object. For me  the best workaround seems to be this

$TestCounter = 1
test( "TestCounter" )
ConsoleWrite( $TestCounter & @LF )

Func test( $nameOfGlobalResultVariable )
    Execute( "global " & $nameOfGlobalResultVariable  )
    Assign( $nameOfGlobalResultVariable , 3 )
EndFunc

Its not perfect but the best compromise between simplicity and proper interface.

 

PS: why havnt you told me about "adlibregister" and let me perform the complicated timer-gui-message-construction?  ^^

kind regards

Edited by Bluesmaster

My UDF: [topic='156155']_shellExecuteHidden[/topic]

Link to comment
Share on other sites

  • Moderators

Bluesmaster,

 

but I have never seen a UDF telling me: "If you use this function you can get your results from the global variable

Then you have not looked at many UDFs - it is a very common method to keep things simple for the user. :)

Look at my GUIListViewEx UDF for example - once you have initiated a listView and stored the integer return value all you need is to use that integer to do all sorts of things. You can access the current content, edit an item or header, set the ListView as active for data manipulation, etc. The UDF uses a fair few Global variables (including a fairly hefty array) but these are completely hidden from the user who only needs to use the public functions to get the UDF to work. ;)

Let me know if I can help you work out a way to get your required result using this concept. :)

M23

P.S. As to AdlibRegister I just assumed given the complexity of the example you posted there was a valid reason for you to use the timer construct. And there is a Help file for you to browse through and look for useful functions. :P

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

The caller does not have to get the result from the global variable, they do not even have to know it's there if you use the return value.

#AutoIt3Wrapper_Run_AU3Check=n

_Main()

Func _Main()
    Local $initialA = 3, $b = 0, $Val = 0
    $Val = _Test($initialA)
    $Val = _Test($b)
    $Val = _Test($b)
    $Val = _Test($b)
    $Val = _Test($b)
    $Val = _Test($b)
    $Val = _Test($b)
    ConsoleWrite("> " & $Val & @LF)
    $first = 0
    ; If you want first called value
    _Test($first, 1)
    ConsoleWrite("- " & $first & @LF)
EndFunc   ;==>_Main


Func _Test(ByRef $PassedArg, $FirstCalled = 0)
    Static $Called = 0
    If Not $Called Then
        Global $TheVar = $PassedArg
        $Called = $PassedArg
    EndIf
    If $FirstCalled Then
        $PassedArg = $Called
        Return
    EndIf

    ConsoleWrite($TheVar & @LF)
    $TheVar += 1
    Return $TheVar
EndFunc   ;==>_test

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

 

The caller does not have to get the result from the global variable

 

But this was the intention of my request. The solution you provided is an identifier system. The caller gets it results by providing an aditional identifier ( in this case just a "1" )

This is ok if you got one caller. But if you got lets say 10 callers who all need their different results you need:

- a more complex system.

- the caller has in any way to maintain this identifier

- the caller has to call the function again later on

All this I wanted to avoid and it occurs, that is not possible. This is ok, I just wanted to know if this is real the case, because I am relativly new to autoIt.

The best thing I learned is  that autoIt has an active and motivated community which is the best argument to continue working with it :thumbsup:

Thank you

Blues

My UDF: [topic='156155']_shellExecuteHidden[/topic]

Link to comment
Share on other sites

Yeah, it's a bit of a bastard really.

You know that objects obey static too?

I made an example of it a while back >here and >here It's not impossible that you might find a way it can help you.

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

I really miss structs in autoIt so this is definitly a snippet for my library. :)

But at least it a contradiction to the basic target: simplicity

So let us just accept its not possible. Sometimes one wins sometimes not. :)

Thank you all for your kind help

regards

Blues

My UDF: [topic='156155']_shellExecuteHidden[/topic]

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