Announcement

Collapse
No announcement yet.

Calling a function using a variable

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Calling a function using a variable

    Is it possible to call a function using a variable that contains the function name?

    I've got a large QB 4.5 app that I'm converting, and this technique is used all over the place.

    Here's an example (converted to PB/CC format):

    Code:
    DIM prg AS STRING
    prg = "FuncName"
    
    ' This following function call causes "Error 462: Undefined SUB/FUNCTION reference"
    CALL prg
    
    
    FUNCTION FuncName() AS LONG
        ' do function stuff here...
    END FUNCTION

  • #2
    As posited, the answer to your question is "no."

    But see 'CALL DWORD' and 'CODEPTR' in the help file.

    BTW, the construct about which you ask was never in any QB 4.5 program source code. Well, not in any compilable source, anyway.
    Michael Mattias
    Tal Systems Inc. (retired)
    Racine WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      It may be possible with an interpreter instead of a compiler. Another method you could use is a translation table, which would be a simple function that would convert the string into a CodePtr() address, which could then be used with the CALL DWORD USING FuncDecl() syntax. The parameters of all functions would have to be the same though.
      kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

      Comment


      • #4
        You could possibly? enumerate the exportable functions of a dll and call any one of them. This link may help. I have not tried it. http://www.powerbasic.com/support/pb...ad.php?t=24322

        Comment


        • #5
          You're right Michael, I've mixed up my thoughts! The original QB4.5 app extensively utilized the CHAIN command, so this is what was done several times over:

          CHAIN prg$

          During conversion to PB/CC, I changed all the CHAIN commands to "CALL prg$", which as you pointed out, doesn't work.

          I guess I need to find a better equivalent to "CHAIN prg$"...

          Comment


          • #6
            Chain

            Dan,

            You can call old QB45 programs from PBCC with the SHELL statement but you will need to add needed values as arguments after your program name.

            See the much improved Shell Statement in the Help Section
            Old QB45 Programmer

            Comment


            • #7
              >I guess I need to find a better equivalent to "CHAIN prg$"...

              No you don't.

              "CALL functionname" is that "better equivalent" ( an oxymoron if ever there was one).

              MCM

              PS:
              You can call old QB45 programs from PBCC with the SHELL statement ..
              You didn't really suggest that, did you?
              Michael Mattias
              Tal Systems Inc. (retired)
              Racine WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                Ok, thanks. I'll stick with the "CALL funtionname" method then.

                I'll see if I can wrap my head around this DWORD/CODEPTR concept, and investigate the possibility of a "lookup table" function using these.

                Comment


                • #9
                  If you are calling a particular function as the result of an evaluation, you might investigate:

                  IF A = B THEN CALL FuncName
                  -or-
                  IF NOT Q THEN CALL DoSomething

                  Just a thought.
                  There are no atheists in a fox hole or the morning of a math test.
                  If my flag offends you, I'll help you pack.

                  Comment


                  • #10
                    Calling old QB45 programs

                    Yes Michael,

                    But, as a stop gap measure only, when you are replacing the old modules with PBCC ones.

                    You have to keep the entire system running while upgrading but I found it much better to rewrite everything from scratch than try to use the old code to save some time.

                    The old Random Access code is so much better when you replace it with Binary Access. I just love that Trick... Sorry... Technique.

                    So, Dan, you should bite the bullet and start with a clean sheet. You will be much better in the end.
                    Old QB45 Programmer

                    Comment


                    • #11
                      I suppose we could just make a big comparison function like Mel suggested above.

                      This old app I'm converting has 200+ EXE (compiled BAS) files that are CHAINed all over the place (not to mention countless "ON KEY/KEY ON/KEY OFF" instances, which is an entirely new painful topic), so I was hoping for a more elegant way to call them via a variable.

                      My company inherited this application, so we're looking to do as little as possible to get it working in PB/CC. The existing QB 4.5 app is very stable, but the code is quite messy. This is all a transitional step towards PB/Win, which is where we'll set our sights once working in PB/CC.

                      Comment


                      • #12
                        By the way, just tried an experiment with CODEPTR. Apparently, it doesn't like variables either:

                        Code:
                        #COMPILE EXE
                        
                        FUNCTION MyFunc() AS LONG
                            PRINT "You called MyFunc()..."
                        END FUNCTION
                        
                        FUNCTION PBMAIN
                            LOCAL MyFuncPtr AS LONG
                        
                            LOCAL funcName AS STRING
                            funcName = "MyFunc"
                        
                            ' This works
                            MyFuncPtr = CODEPTR(MyFunc)
                        
                            ' But this doesn't
                            MyFuncPtr = CODEPTR(funcName)
                        
                            CALL DWORD MyFuncPtr
                        END FUNCTION

                        Comment


                        • #13
                          CodePtr() needs an actual FUNCTION/SUB name, it will not work with a variable. If you want to call functions in an EXE by literal name, you'll need some sort of translation function, as the following example shows:

                          Code:
                          #Compile Exe
                          #Dim All
                           
                          Function MyFunc1() As Long
                              ? "You called MyFunc1()..."
                          End Function
                           
                          Function MyFunc2() As Long
                              ? "You called MyFunc2()..."
                          End Function
                           
                          Function Translation(ByVal sFunction As String) As Dword
                            Select Case Const$ UCase$(Trim$(sFunction))
                                   Case "MYFUNC1": Function = CodePtr(MyFunc1)
                                   Case "MYFUNC2": Function = CodePtr(MyFunc2)
                            End Select
                          End Function
                           
                           
                          Function PBMain
                           
                              Local MyFuncPtr As Dword
                              Local funcName As String
                           
                              funcName = "MyFunc1" ' <  Try
                              'funcName = "MyFunc2" ' < Either
                           
                              MyFuncPtr = Translation(funcName)
                           
                              If (MyFuncPtr) Then Call Dword MyFuncPtr
                           
                          End Function
                          kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

                          Comment


                          • #14
                            Dan,

                            Would it be possible to put everything in 1 program? PB CC can handle
                            quite large amounts of source. I would recommend doing as Guy suggested
                            and start with a clean slate as it will save a LOT of headaches later on.
                            Probably most of the code will be usable with small changes. If not then
                            take the time & code "what it should do" if you find that it is too sloppy
                            as is.

                            But if you don't want to do all that work now then redo the main program
                            over in PB and copy in the old sources 1 at a time ( making what changes
                            are needed ) and you can GOTO the first function of the merged program.
                            You'll probably have problems with function names & making sure that all
                            code is in either a function or a sub but whatever you can do to get
                            it all compilable in CC will certainly help when you move on to PB Win.

                            I take it that this is probably some sort of data entry program with
                            built-in reports?

                            I realize that this is straying far from your original question but it might
                            be useful info.

                            Comment


                            • #15
                              Worst case scenario to merge all into one program:

                              You put SUB programname () ...END SUB around all code in each program which is not currently located in a procedure......

                              I take it back.. the worst case scenario is SHARED variables with same name in each separate program ... so first thing you do is in each program do a global seach and replace of "varname" with "programname_varname".

                              Then you can do the SUB.. END SUB thing.

                              MCM
                              (See? SHARED/GLOBAL variables are a PITA after all!)
                              Michael Mattias
                              Tal Systems Inc. (retired)
                              Racine WI USA
                              [email protected]
                              http://www.talsystems.com

                              Comment


                              • #16
                                Thanks for the help so far, it's much appreciated!

                                Merging these into a monolithic program is actually what I've been doing up to this point.

                                In the old version, there are no programs that have functions or subs. They're just straight code from first to last line. This makes it very easy to put each file into a function.

                                So these:

                                program1.bas
                                program2.bas
                                program3.bas
                                ...etc...

                                became these:

                                FUNCTION program1() AS LONG ... END FUNCTION
                                FUNCTION program2() AS LONG ... END FUNCTION
                                FUNCTION program3() AS LONG ... END FUNCTION
                                ...etc...

                                Should I be using SUBs instead of FUNCTIONs?

                                There are only less than ten COMMON vars, which I changed to GLOBAL, as per a QB->PB thread I saw here a while back.

                                Is it really necessary to rename every variable from "varname" to "program_varname"? Since all these programs are in their own functions, should the scope of these non-GLOBAL vars stay within the function? I can see your point if you are doing it only for readability's sake.

                                Another thing I've run into, is that the old app has duplicate var names with different data types. PB/CC doesn't like this. For example, I'd have vars like this:

                                VAR1$
                                VAR1

                                So, I just renamed them to:

                                VAR1_STR
                                VAR1

                                A pain, but it seems to work.

                                Comment


                                • #17
                                  If you never had any procedures (SUBs or FUNCTIONs) in any of those programs, then making the variables LOCAL is just fine... perfect in fact and no, you don't have to rename them.

                                  I guess I am just used to looking at QB 4.5 which do use procedures, and because of that seem to always use SHARED or COMMON variables.

                                  You have lucked out big-time.

                                  BTW, if you have duplicate names like that, I think using #DIM ALL would be a good idea, as you never know what's lurking in an old program file. (It's also IMO a very good habit to acquire).
                                  Michael Mattias
                                  Tal Systems Inc. (retired)
                                  Racine WI USA
                                  [email protected]
                                  http://www.talsystems.com

                                  Comment


                                  • #18
                                    If it helps any for a function despatch, the good old ON n GOTO/GOSUB statements are still available!
                                    - LJ

                                    Comment


                                    • #19
                                      Oh, there's a huge number of GOSUBs in this code... probably shouldn't go adding many more!

                                      We haven't gone through 100% of the old code yet, so we may yet run into some procedures. We've browsed probably half of it though, and so far so good. Every one of the programs have been self-contained, which is very nice. Here's hoping it continues that way.

                                      Good advice on that #DIM ALL, thanks. It's currently set to #DIM NONE. I had wondered about that earlier, but forgot to follow up on it.

                                      Comment


                                      • #20
                                        As a word of note: GOSUB's are only valid in the SUB/FUNCTION calling them. Trying to GOSUB outside the sub/function won't work. I don't think it will even compile. For example, the following code is valid:
                                        Code:
                                        function DoSomething
                                        ...process
                                        ...process
                                        GOSUB somewhere
                                        ...process
                                        ...process
                                        exit function    '< To avoid a RETURN without GOSUB error message
                                        
                                        somewhere:
                                        ...
                                        ...
                                        return
                                        end function

                                        The following code is NOT valid. It's outside the calling function:
                                        Code:
                                        function DoSomething
                                        ...
                                        ...
                                        gosub somewhere
                                        ...
                                        ...
                                        end function
                                        
                                        somewhere:
                                        ...
                                        ...
                                        return
                                        This little detail caused me some head scratching when I was learning CC.
                                        Last edited by Mel Bishop; 17 Sep 2008, 07:53 PM.
                                        There are no atheists in a fox hole or the morning of a math test.
                                        If my flag offends you, I'll help you pack.

                                        Comment

                                        Working...
                                        X