Sign in to follow this  
Followers 0
jvanegmond

_CallAny UDF function & Call with ByRef

16 posts in this topic

#1 ·  Posted (edited)

This call function can call any script/user function and also any native function. This is invented because mostly invented this clumsy work-around.

For call with ByRef capability (but only with CallArgArray), see this post:

Hopefully at some point AutoIt will treat AutoIt functions as-if they were user defined functions (or vice versa). Reposted this in a seperate thread for SEO mostly (<title> and <h1> matter most, after all).

_CallAny("MsgBox", 0x20, "Hello, World", "LOL")

; This demonstrates how to use the special array argument.
Local $aArgs[4]
$aArgs[0] = "CallArgArray" ; This is required, otherwise, _CallAny will not recognize the array as containing arguments
$aArgs[1] = 0x20
$aArgs[2] = "Hello, World"
$aArgs[3] = "Example 2"

_CallAny("MsgBox", $aArgs)

Func _CallAny($function, $param1 = 0, $param2 = 0, $param3 = 0, $param4 = 0, $param5 = 0)
    Local $exec = $function & "("
    If @NumParams = 2 And IsArray($param1) And UBound($param1, 0) = 1 And $param1[0] = "CallArgArray" Then
        For $n = 1 To UBound($param1) - 1
            $exec &= "$param1[" & $n & "],"
        Next
    Else
        For $n = 1 To @NumParams
            $exec &= "$param" & $n & ","
        Next
    EndIf
    Local $iRet = Execute(StringTrimRight($exec, 1) & ")")
    Return SetError(@error, @extended, $iRet)
EndFunc ;==>_CallAny

To add the ability for more parameters, just add $param6 = 0, $param7 = 0. The guts of the function don't need any changes.

Edited by Manadar
1 person likes this

Share this post


Link to post
Share on other sites



Why run native functions this way if the features already native, is part of the current script!

Call("MsgBox", 0x20, "Hai there", "What's up?")

Run it and see what happens.

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Call("MsgBox", 0x20, "Hai there", "What's up?")

Run it and see what happens.

Cool I saw how it works.

But why create a UDF to call features that already native?

Note: In an interpreted scripting language in this way it would be more an interpretation...

Edited by jscript

http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Cool I saw how it works.

But why create a UDF to call features that already native?

It has many uses. For example, I was just playing with this:

$gui = "$hWnd, Form, 'Oh hi', 300, 300, 0, 0" & @CRLF & _
       ", Group, 'What''s up', 5, 5, 290, 290" & @CRLF & _
       "$bClick, Button, 'Click me!', 90, 90, 100, 100"

_QuickGUI($gui)

ConsoleWrite("$bClick = " & Eval("bClick") & @CRLF)

Sleep(5000)

Func _QuickGUI($content)
    Local $controls[3][2] = [["Form", "GUICreate"], ["Group", "GUICtrlCreateGroup"], ["Button", "GUICtrlCreateButton"]]
    $lines = StringSplit(StringStripCR($gui), @LF)
    For $i = 1 To UBound($lines)-1
        $line = $lines[$i]
        $split = StringSplit($line, ",")
        Assign(StringStripWS($split[1], 8), _CallAny(_DictGetValue($controls, StringStripWS($split[2], 8)), $split[3], $split[4], $split[5], $split[6], $split[7]), 2)
    Next
    GUISetState()
EndFunc

Func _DictGetValue($dict, $key) ; Standardize this function? It's a nice one to have at all times
    For $i = 0 To UBound($dict)-1
        If $dict[$i][0] = $key Then
            Return $dict[$i][1]
        EndIf
    Next
    Return SetError(1, 0)
EndFunc

Func _CallAny($function, $param1 = 0, $param2 = 0, $param3 = 0, $param4 = 0, $param5 = 0, $param6 = 0)
    Local $exec = $function & "("
    If @NumParams = 2 And IsArray($param1) And UBound($param1, 0) = 1 And $param1[0] = "CallArgArray" Then
        For $n = 1 To UBound($param1) - 1
            $exec &= "$param1[" & $n & "],"
        Next
    Else
        For $n = 1 To @NumParams
            $exec &= "$param" & $n & ","
        Next
    EndIf
    $exec = StringTrimRight($exec, 1) & ")"
    Return Execute($exec)
EndFunc ;==>_CallAny

Really ugly code, because sometimes I just like to get dirty. and I'm sure hyperzap has a pretty good reason also for doing what he does. ( I think it was for AutoIt interpreter or something ).

To me it seems to only make sense to also be able to dynamic execute native functions in a dynamic language.

Edited by Manadar

Share this post


Link to post
Share on other sites

It appears only that!

>Running:(3.3.6.1):D:\Program Files\AutoIt3\autoit3.exe "D:\AutoIt v3 - Projects\Temp\_CallAny.au3"    
$bClick = 
+>11:27:03 AutoIT3.exe ended.rc:0
>Exit code: 0    Time: 6.234

http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Share this post


Link to post
Share on other sites

Function Call() doesn't make much sense if not used with array (CallArgArray). If I'm asked I would say -remove that feature from the language.

On the other hand, ability to accept array of parameters is simply brilliant. That's the main power of that function. The only downside (and a big one)is lack of ByrRef.

Can I play with it?

; This demonstrates how to use the special array argument.
Global $aArgs[4]
$aArgs[0] = "CallArgArray" ; This is required, otherwise, Call() will not recognize the array as containing arguments
$aArgs[1] = 64 + 262144
$aArgs[2] = "Hello, World"
$aArgs[3] = "LOL"

$result = _CallArgArray("MsgBox", $aArgs)
$result = _CallArgArray("_MsgBox", $aArgs)

$result = _CallArgArray("_MsgBox", $aArgs)
ConsoleWrite("@error = " & @error & ", @extended = " & @extended & ", $result = " & $result & @CRLF)

Func _CallArgArray($sFunc, ByRef $vParam)
    Local $sExec = $sFunc & "("
    If IsArray($vParam) And UBound($vParam, 0) = 1 And $vParam[0] = "CallArgArray" Then
        For $n = 1 To UBound($vParam) - 1
            $sExec &= "$vParam[" & $n & "],"
        Next
    Else
        Return SetError(0xDEAD, 0xBEEF) ; invalid parameter
    EndIf
    Local $iRet = Execute(StringTrimRight($sExec, 1) & ")")
    Return SetError(@error, @extended, $iRet)
EndFunc   ;==>_CallArgArray

Func _MsgBox(ByRef $iFlag, ByRef $sTitle, ByRef $sText, $iTimeout = 0, $hWnd = 0)
    Local $iRet = MsgBox($iFlag, $sTitle, $sText, $iTimeout, $hWnd)
    $sTitle = "New title"
    $sText = "New text"
    $iFlag = 32 + 262144
    Return $iRet
EndFunc   ;==>_MsgBox

.. it makes sense to me now.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

Here's an obfuscator proof version. The only time this will fail is if the function name that you are calling changes (e.g. calling a non native function).

Local $a[4] = ["CallArgArray", 2, "Hello, World", "LOL"]

_CallAny("MsgBox", $a)
_CallAny("MsgBox", 2, "Hello, World", "LOL")

Func _CallAny($function, $param1 = 0, $param2 = 0, $param3 = 0, $param4 = 0)
    Local $ret

    If @NumParams > 1 Then
        Local $aParamVars[@NumParams - 1]
        Local $sParams = ""

        For $i = 0 To @NumParams - 2
            $aParamVars[$i] = Hex(Random(1000, 100000, 1))
        Next

        If @NumParams > 1 Then
            Assign($aParamVars[0], $param1)

            If @NumParams > 2 Then
                Assign($aParamVars[1], $param2)

                If @NumParams > 3 Then
                    Assign($aParamVars[2], $param3)

                    If @NumParams > 4 Then
                        Assign($aParamVars[3], $param4)

                        ; ... Add more?
                    EndIf
                EndIf
            EndIf
        EndIf
    EndIf

    If @NumParams = 2 And IsArray($param1) And UBound($param1, 0) = 1 And $param1[0] = "CallArgArray" Then
        For $i = 1 To UBound($param1) - 1
            $sParams &= "$" & $aParamVars[0] & "[" & $i & "],"
        Next
        $sParams = StringTrimRight($sParams, 1)

        $ret = Execute($function & "(" & $sParams & ")")
    Else
        For $i = 0 To @NumParams - 2
            $sParams &= "$" & $aParamVars[$i] & ","
        Next
        $sParams = StringTrimRight($sParams, 1)

        $ret = Execute($function & "(" & $sParams & ")")
    EndIf

    Return $ret
EndFunc   ;==>_CallAny

Edit: This acts exactly like the internal function in all ways but returning 0xDEAD. Other than that it is a direct replacement even when ofuscated :unsure:

Edited by Mat

Share this post


Link to post
Share on other sites

Function Call() doesn't make much sense if not used with array (CallArgArray). If I'm asked I would say -remove that feature from the language.

On the other hand, ability to accept array of parameters is simply brilliant. That's the main power of that function. The only downside (and a big one)is lack of ByrRef.

Can I play with it?

.. it makes sense to me now.

Creative usage. :unsure: I wish that we could pass both ByRef and default parameter. (Simply ignore changed value with ByRef)

Share this post


Link to post
Share on other sites

Sorry, but 0xDEAD, 0xBEEF

Ha! :unsure:


Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Share this post


Link to post
Share on other sites

Sorry, but 0xDEAD, 0xBEEF

Ha! :unsure:

Yea, it's funny :>

It's standard Call() response, I only replicated the behavior.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

Creative usage. :unsure: I wish that we could pass both ByRef and default parameter. (Simply ignore changed value with ByRef)

You could create a ByRef effect if you didn't use an array for parameters and used some global variables.

EDIT. I didn't mean for native functions

Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

@Manadar

I'm starting to like your idea... (not for native functions)

@trancexx

ByRef passing as a parameter is an excellent idea!

I'll try to adapt here:


http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

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  
Followers 0