Author Topic: is there a way to get the name of a function to call from a variable or data?  (Read 5329 times)

0 Members and 1 Guest are viewing this topic.

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
    • View Profile
In VBA, you can do something like
Code: Text: [Select]
  1. sFunctionName = "MyFunction"
  2. sParameter1 = "MyValue"
  3. If Len(Trim(sFunctionName)) > 0 Then
  4.         If Len(sParameter1) = 0 Then
  5.                 Application.Run sFunctionName
  6.         Else
  7.                 Application.Run sFunctionName, sParameter1
  8.         End If
  9. End If
  10.  

Is there any way to do this kind of thing in QB64?

I know that using eval and running code from data isn't the most "secure" practice, and for anything public-facing I would avoid it,
but it can come in handy for testing a large number of functions or quickly (re)defining a menu in data when prototyping a design, etc.

Offline luke

  • Administrator
  • Seasoned Forum Regular
  • Posts: 324
    • View Profile
In a word, no. VBA can easily do this by virtue of being an interpreted language; QB64 is always compiled which makes such things much harder (I'm sure someone will come up with a hack using DECLARE LIBRARY to prove me wrong).

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Hi @madscijr,

a while back I made some experiments, but only with parameterless functions. You need to know the names of your SUBs/FUNCs at the C side of things (usually the all uppercase name + SUB_/FUNC_ prefix) and define helper functions to take their address (_OFFSET), over which you can later call it.

save as hookfunc.h
Code: C: [Select]
  1. // stubs to get the addresses of the defined QB64 SUBs/FUNCs
  2. // there must be an entry for each SUB/FUNC you need
  3. int16 FUNC_TEST(); ptrszint GetHook_Test(void) {return (ptrszint)&FUNC_TEST;}
  4. int16 FUNC_TEST2(); ptrszint GetHook_Test2(void) {return (ptrszint)&FUNC_TEST2;}
  5.  
  6. // call the function via its address, which on QB64 side may be stored
  7. // in a _OFFSET variable, if you need other return types, then you may
  8. // copy this typdef & function with slighly different names and redefine
  9. // the int16 type as needed, however no tests yet how to pass arguments
  10. typedef int16 (*fp)();
  11. int16 CallHook(ptrszint hook) {
  12.     fp func = (fp)hook;
  13.     return func();
  14. }
  15.  
  16.  

save as hookfunc.bas
Code: QB64: [Select]
  1. 'the functions in hookfunc.h
  2. DECLARE LIBRARY "hookfunc" 'no .h here !!
  3.     FUNCTION GetHook_Test%& ()
  4.     FUNCTION GetHook_Test2%& ()
  5.     FUNCTION CallHook% (BYVAL hook%&)
  6.  
  7. 'get/print address of FUNCTION Test%
  8. h%& = GetHook_Test%&
  9. PRINT h%&
  10. 'call FUNCTION Test% via its address
  11. PRINT CallHook%(h%&)
  12.  
  13.  
  14. 'get/print address of FUNCTION Tes2%
  15. h%& = GetHook_Test2%&
  16. PRINT h%&
  17. 'call FUNCTION Test2% via its address
  18. PRINT CallHook%(h%&)
  19.  
  20. 'that all folks
  21.  
  22. FUNCTION Test% ()
  23. PRINT "This is function Test%()"
  24. Test% = 0
  25.  
  26. FUNCTION Test2% ()
  27. PRINT "This is function Test2%()"
  28. Test2% = -1
  29.  
  30.  
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
    • View Profile
In a word, no. VBA can easily do this by virtue of being an interpreted language; QB64 is always compiled which makes such things much harder (I'm sure someone will come up with a hack using DECLARE LIBRARY to prove me wrong).

That's about what I expected - thanks for the swift response! It's not a feature I will die without, so no worries, I just figured it can't hurt to ask.

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
    • View Profile
a while back I made some experiments, but only with parameterless functions. You need to know the names of your SUBs/FUNCs at the C side of things (usually the all uppercase name + SUB_/FUNC_ prefix) and define helper functions to take their address (_OFFSET), over which you can later call it.

Wow, interesting. This should be fun to play with. You are truly a wizard! Thanks for sharing that workaround!

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
There's another way of doing this that's slightly more intuitive. I'll see if I can find my code for it
Shuwatch!

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
    • View Profile
There's another way of doing this that's slightly more intuitive. I'll see if I can find my code for it

Sure, I would love to see what can be done.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
You could read the source file and make a list of functions used, pretty easy.

You could dim shared a variable string, Iam$ and label all your functions with Iam$ = function name then just print the function name when ever needed.

Another: You could make a menu and call what ever function you want to check

Solutions that don't need anything special.

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
    • View Profile
Solutions that don't need anything special.

That's what I ended up doing - you'll see when I post the next program (a collection of audio examples).