Returning Data from Dynamically Called Functions in PlayBASICIn 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]
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
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)