UnderwareDESIGN

PlayBASIC => Resources => Source Codes => Topic started by: kevin on August 12, 2024, 12:18:51 PM

Title: Returning Data from Dynamically Called Functions in PlayBASIC
Post by: kevin on August 12, 2024, 12:18:51 PM
Returning Data from Dynamically Called Functions in PlayBASIC


In this example source code we use a user defined type (a structure) to hold our return type from a function call.  This is really handle approach for when dynamically calling functions in your PlayBASIC programs using CallFunction   

Simple, but powerful pattern to wrap your coding brain around ! 



[pbcode]

    Type tReturn
            DataType
            iValue
            fValue#
            sString$
    EndType

    dim Result as tReturn pointer
    Result = new tReturn

    for lp =0 to 20
            Index=wrapvalue(Index+1,1,4)
            Name$="Work_Function_"+digits$(index,2)
            callFunction Name$,result

            // display what's in the result structure
            Name$+=" returns "+GetReturn(Result)
            print Name$
       
    next
    sync
    waitkey
   



        //  Test worker functions that are called by name that we
        // need to return data from. 


Function  Work_Function_01(result as tReturn pointer)
            ReturnInteger(result, 100)
EndFunction

Function  Work_Function_02(result as tReturn pointer)
            ReturnFloat(result, 123.456)
EndFunction



Function  Work_Function_03(result as tReturn pointer)
            ReturnString(result, "MyString"+str$(rnd(100)) )
EndFunction


        //  Functins to set and get the return data structure. 


function GetReturn(Output as tReturn pointer)
            select Output.datatype
                        case 1
                            Result$="Integer:"+str$(output.ivalue)
                        case 2
                            Result$="float:"+str$(output.fvalue)
                        case 3
                            Result$="String:"+output.sstring
            endselect
ENdFunction result$

Function ReturnInteger(Output as tReturn pointer, ThisInteger)
    Output.DataType =1
    Output.iValue = ThisInteger
ENdFunction

Function ReturnFloat(Output as tReturn pointer, ThisFloat#)
    Output.DataType =2
    Output.fValue = ThisFloat#
ENdFunction

Function ReturnString(Output as tReturn pointer, ThisString$)
    Output.DataType =3
    Output.sString =  ThisString$
ENdFunction

[/pbcode]







  Example #2  - As seen in the video


 

[pbcode]

    Type tReturn
            DataType
            iValue
            fValue#
            sString$
    EndType

    dim CallFunctionResult as tReturn
    CallFunctionResult= new tReturn
   
    for lp =0 to 20
            Index=wrapvalue(Index+1,1,4)
            Name$="Work_Function_"+digits$(index,2)
            callFunction Name$

            // display what's in the result structure
            Name$+=" returns "+GetReturn()
            print Name$
       
    next
    sync
    waitkey
   



        //  Test worker functions that are called by name that we
        // need to return data from. 


Function  Work_Function_01()
            ReturnInteger( 100)
EndFunction

Function  Work_Function_02()
            ReturnFloat( 123.456)
EndFunction

Function  Work_Function_03()
            ReturnString("MyString"+str$(rnd(100)) )
EndFunction


        //  Functins to set and get the return data structure. 

function GetType()
            result=CallFunctionResult.dataType
EndFunction result


function GetReturn()
            select GetType()
                        case 1
                            Result$="Integer:"+str$(CallFunctionResult.ivalue)
                        case 2
                            Result$="float:"+str$(CallFunctionResult.fvalue)
                        case 3
                            Result$="String:"+CallFunctionResult.sstring
            endselect
ENdFunction result$

Function ReturnInteger(ThisInteger)
    CallFunctionResult.DataType =1
    CallFunctionResult.iValue = ThisInteger
ENdFunction

Function ReturnFloat(ThisFloat#)
    CallFunctionResult.DataType =2
    CallFunctionResult.fValue = ThisFloat#
ENdFunction

Function ReturnString(ThisString$)
    CallFunctionResult.DataType =3
    CallFunctionResult.sString =  ThisString$
ENdFunction




[/pbcode]

Title: Re: Returning Any data type from a function by using a return structure
Post by: kevin on August 13, 2024, 10:49:09 PM
Variants - Variable Input Parameters in Function Calls


  Here's the basic usage 


[pbcode]

    type tInputParams
            X,Y
            TITLE$   
            Colour
    EndType

    Dim Inputs as tInputParams pointer
    inputs=new tInputParams
       



    for lp =0 to 20
            Index=wrapvalue(Index+1,1,4)

            Name$="Work_Function_"+digits$(index,2)


                Inputs.x = 600
                Inputs.y = 200
                inputs.title    = "DUDE WHERES MY CAR?"


                //  Push
                FlushParameters()
                PushParamInt(        "X"        ,600)
                PushParamInt(        "Y"        ,200)
                PushParamString(    "TITLE"    ,"DUDE WHERES MY CAR?")
                PushParamInt(        "JUNK"    ,99999)
            callFunction Name$, Inputs
           

            // display what's in the result structure
            Name$+=" returns "+GetReturn()
            print Name$
       



                // Test calling a functin wit
                Work_Function_TEST(Inputs)


    next
    sync
    waitkey
   

   

        //  Test worker functions that are called by name that we
        // need to return data from. 

Function  Work_Function_TEST(Params as tInputParams pointer)

                // f
                X        =Params.X
                Y        =Params.Y
                Title$=Params.Title$

                X+=200
                Circlec X,Y,100,true,$00ff00
                ink $00
                centertext x,y,Title$
                ink -1

                // Return
            ReturnInteger( 100)
EndFunction




Function  Work_Function_01(Params as tInputParams pointer)

                // Decode pushed parameters by name
                repeat
                    Name$=ParamName$()
                    Select Name$
                        case "X"        : X        = GetParamINT()
                        case "Y"        : Y        = GetParamINT()
                        case "TITLE"    : TITLE$    = GetParamSTRING$()
                        default            : SkipParam()
                    EndSelect
                until len(Name$)=0   

                Circle X,Y,100,true
                ink 0
                centertext x,y,Title$
                ink -1

                // Return
            ReturnInteger( 100)
EndFunction

Function  Work_Function_02(Params as tInputParams pointer)
   
                boxc 700,100,750,800,true,$ff0000
            ReturnFloat( 123.456)
EndFunction

Function  Work_Function_03(Params as tInputParams pointer)
   
                line params.x,params.y,rnd(800),rnd(800)

            ReturnString("MyString"+str$(rnd(100)) )
EndFunction




[/pbcode]



  Ideas on Dynamically Passing Arguments in PlayBASIC

 


  Commands Usage

    - CallFunction (https://playbasic.com/help.php?page=CORE%20COMMANDS.CALLFUNCTION)



DownLoad

    Full Code attached
Title: Re: Returning Data from Dynamically Called Functions in PlayBASIC
Post by: kevin on August 15, 2024, 10:55:54 PM
Variants - Variable Input Parameters in Function Calls V003

  This is a more elegant way of achieving argument passing into dynamically called functions.  The idea being is that the function prototypes (the pattern of parameters) are not all the same,  but if we push all the things we need, then call  our function and let it grab what it needs we can decouple of the code block from each other.  So the functions don't need to call back or access global structures. 



[pbcode]

; PROJECT : 2024-08-13 - Variant - Function Calling - V003
; AUTHOR  : Kevin Picone - PlayBASIC Tutor - https://PlayBASIC.com
; CREATED : 13/08/2024
; EDITED  : 16/08/2024
; ---------------------------------------------------------------------


    Dim Messages$(100)
   
    Do
        Cls

        GridX=200
        GridY=200
        X=GridX/2
        Y=GridY/2

           
        for lp =0 to 20
            Index=wrapvalue(Index+1,1,4)

            Name$="Work_Function_"+digits$(index,2)

                //  Push
                FlushParameters()
                PushParamInt(        "X"        ,X)
                PushParamInt(        "Y"        ,Y)
                PushParamString(    "TITLE"    ,"DUDE WHERES MY CAR?"+str$(lp))
                PushParamInt(        "MOUSEX"            ,mouseX())
                PushParamInt(        "MOUSEY"            ,mouseY())
                PushParamInt(        "MOUSEBUTTON"    ,mousebutton())
            callFunction Name$

            // display what's in the result structure
            Messages$(lp)=Name$+" returned "+GetReturn()

                if (X+GridX)>=GetSurfaceWidth()
                    X=gridX/2
                    Y+=GridY
                    if Y>GetSurfaceHeight() then exit
                else
                    X+=GridX   
                endif
               
        next
       
            // draw the messages over the top of the display
        for lp=0 to GetArrayelements(Messages$())
            m$=Messages$(lp)
            if len(m$) then print m$
        next


        sync
    loop
   



Function  Work_Function_01()

                //  Get our variables from the stack, in the type we want them
                X        =GetIntVariable("X")           
                Y        =GetIntVariable("Y")           
                Title$=GetStringVariable$("TITLE")

                Circlec X,Y,100,true,$334455
                ink 0
                centertext x,y,Title$
                ink -1

                // Return
            ReturnInteger( X)
EndFunction

Function  Work_Function_02()
   
                X        =GetIntVariable("X")           
                Y        =GetIntVariable("Y")           
                Title$=GetStringVariable$("TITLE")

                Radius=95
                boxc x-Radius,y-Radius,X+Radius,Y+Radius,true,$ff00ff

                ink 0
                centertext x,y,Title$
                ink -1

            ReturnFloat( X*Y )
EndFunction

Function  Work_Function_03()
   
                // This Function only needs the X/Y and Mouse cords
                // so that's all we read
                X        =GetIntVariable("X")           
                Y        =GetIntVariable("Y")           
                MX        =GetIntVariable("MOUSEX")           
                MY        =GetIntVariable("MOUSEY")           

                // compute the direction of the mouse cursor from this point
                Angle#=getangle2d(x,y,mx,my)
                x2        =x+cos(angle#)*45
                y2        =y+sin(angle#)*45
               
                // draw a line from the grid X/Y towards the mouse
                line X,Y,x2,y2

            ReturnString("MyString"+str$(XPOS) )
EndFunction






[/pbcode]




  Download Full Source Code:

  Attached bellow (login)