B4R Question CallSubPlus(variableString....) Not possible at all?

Cableguy

Expert
Licensed User
Longtime User
Hi guys...

I am trying to create a code module with some "utility" code... Amid these, I want to recreate a "RandomTimer" alike funcion, but I block at the main code line that actually executes this...
CallSubPlus(SubName as SubVoidByte, MsDelay as ULong, Tag as Byte) >>>> How can I pass a variable string as the subName?
In B4R Non-Primitives are transformed into Constants, so SubName is expected to be a String Constant... so how can I pass a string variable between subs so that I can use it in my CallSubPlus call?????
 

hatzisn

Expert
Licensed User
Longtime User
I do not think you can. But check setting a string variable in the same sub and passing it to callsubplus, just out of curiosity. Otherwise a "select case" is your answer.
 
Upvote 0

Cableguy

Expert
Licensed User
Longtime User
a select case implies knowing before hand the available sub names I may call...
This said, I came to realize that B4R does not allow to create other than Code Modules so, I cannot re-use the code module as object (as one would in a lib), so I will need to hardcode the subname anyway...

Still, the main question remains... How to pass a variable string between subs
 
Upvote 0

hatzisn

Expert
Licensed User
Longtime User
Search for GlobalStore.
 
Upvote 0

Cableguy

Expert
Licensed User
Longtime User
I already did that, but the problem remains, if you do something like

dim mString as String = "myString"
GlobalStore.put(0, mString)

And then you try to use it in another sub, replacing a String Argument with GlobalStore.Slot(0) you get an error complaining that it expects a String Constant
 
Upvote 0

hatzisn

Expert
Licensed User
Longtime User
Oh, sorry. I thought that you would use the string constant in CallSubPlus and you just wanted to pass a string value to it.
 
Upvote 0

Cableguy

Expert
Licensed User
Longtime User
B4R was created when Arduino was in fact very "resources challenged" but now, with ESP32 having up to 4Mb Ram, and clock frequencies that allow for almost multitasking, It would be more than time to bring B4R up to date with some major upgrades memory management wise.
I also find that most HD lib were also created for now obsolete microcontrollers, and that Arduino Uno is no longer the microcontroller reference in the maker world, new libs should be considered
 
Upvote 0

Cableguy

Expert
Licensed User
Longtime User
Oh, sorry. I thought that you would use the string constant in CallSubPlus and you just wanted to pass a string value to it.
I did, and that is how I found that even using GlobalStore does not work
 
Upvote 0

hatzisn

Expert
Licensed User
Longtime User
I did, and that is how I found that even using GlobalStore does not work

Maybe I did not express myself correctly. What I meant was call the sub with CallSubPlus using the sting constant and once you are inside the sub use the string in Globalstore.Slot(0).
 
Upvote 0

zed

Well-Known Member
Licensed User
You cannot pass a subroutine name as a variable in B4R, because the compiler converts all non-constant strings to fixed values at compile time.
More importantly, B4R does not allow dynamically calling a subroutine by its name.

CallSubPlus(SubName as SubVoidByte, MsDelay as ULong, Tag as Byte)
Here, "SubName" is not a string, but a function pointer generated by the compiler.
Therefore, you must pass the sub's name directly, never a variable.

In B4R, strings are not dynamic; they become constants in ROM. There is no reflection mechanism like in B4A/B4J.
The compiler must know at compile time which function will be called.

You can create an array of function pointers and select one of them via an index.
Example:
Sub Process_Globals
    Public Sub1 As SubVoidByte
    Public Sub2 As SubVoidByte
    Public FuncTable(2) As SubVoidByte
End Sub

Sub AppStart
    FuncTable(0) = Sub1
    FuncTable(1) = Sub2

    Dim idx As Byte = 1
    CallSubPlus(FuncTable(idx), 1000, 0)
End Sub

Sub Sub1(Tag As Byte)
    Log("Sub1 exécutée")
End Sub

Sub Sub2(Tag As Byte)
    Log("Sub2 exécutée")
End Sub
Here, you pass an index, not a name.


You can use a Select Case in a generic sub. You always call the same sub, and you decide what to do based on an identifier.
Example:
CallSubPlus(Dispatcher, 1000, 2)

Sub Dispatcher(Tag As Byte)
    Select Tag
        Case 1
            Action1
        Case 2
            Action2
    End Select
End Sub

Alternatively, use a custom type containing a function pointer. B4R allows you to store a SubVoidByte in a type.
Example:
Type Task(SubPtr As SubVoidByte, Delay As Long, Tag As Byte)

Dim t As Task
t.SubPtr = Action1
t.Delay = 500
t.Tag = 7

CallSubPlus(t.SubPtr, t.Delay, t.Tag)


In conclusion, you cannot pass a subname as a string.
You must pass a function pointer, which is known at compile time.


If I'm wrong, please tell me.
 
Upvote 0
Top