No announcement yet.

A stupid question about DLL's

  • Filter
  • Time
  • Show
Clear All
new posts

  • A stupid question about DLL's

    Is it possible for a PB DLL to create an array and pass it back
    to the calling EXE, which hadn't created the array? My logic
    dictates that such a thing would be impossible. The only
    workaround I can think of would be to have the DLL create the
    array, then have it create a PTR to the array, and pass the PTR
    back to the EXE.

    Thanks in advance!

    Clay Clear

    Clay C. Clear

    Head SysOp/Owner
    Clear's Critters BBS
    Node 1: (218) 229-2593
    Node 3: (218) 229-2353

  • #2

    You are almost there, However do not forget that if you create a variable
    in a function, then that variable will be destroyed when the function
    exits unless you do something clever.

    Therefore if you create an array in a DLL function then pass a pointer
    back to the calling program, the pointer will point to garbage and
    would probably GPF because the array would no longer exist.

    You would probably need to create the array in your calling program
    and send the pointer to the DLL. That way when the DLL returns, it
    will not destroy the variable because it didn't create it.




    • #3

      Thanks for your reply! I never thought about functions destroying
      their variables upon exit. Well, nothing's lost, as I haven't
      coded any DLL's to create arrays themselves (except for LOCAL
      ones). I've already been writing my EXE's so THEY create the
      arrays and pass them to the DLL's. So, you just saved me a bunch
      of test coding. Thanks, once again!


      Clay C. Clear

      [email protected]
      [email protected]


      • #4
        Well, no you can't create an array in a DLL as a local (or GLOBAL) variable and use it in your "main" program, but I do this all the time:

        ' MAIN PROGRAM
         FUNCTION MainOne (whatever)
           REDIM X(0) AS whatever ' create dynamic array
           CALL FunctionInDLL (X())
           DoWhatever (x(now a new size and filled with data))
        ' FOO.DLL
        FUNCTION FunctionInDLL (X() AS whatever) EXPORT as whatever
           NewArraySize = whatever
           REDIM X(NewArraySize) AS whateverbutsameaspassed
        That is, you create a minimal array in your main program but do all the real work in your DLL.

        Since DIM/REDIM are required in the main program to do anything with the data anyway, this costs you nothing.

        There are some other ways to deal with your challenge, but none is as strightforward as this.


        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]


        • #5
          Well this is an interesting topic.. And kinda spins off of the idea
          of MEMORY ALLOCATION in PowerBasic. In the case that you could
          allocate memory locations you could make a array (64K limitted) and
          pass the pointer back to a .EXE like you needed..

          Maybe PB should the ability to allocate memory larger than 64K...
          Just thinking..

          Explorations v3.0 RPG Development System

          Explorations v9.10 RPG Development System


          • #6
            Tyrone, where did you get this 64K limit idea from???

            In PB/DLL and PB/CC, you can allocate *massive* blocks of memory, up to 2Gb. Remember, your PB/DLL and PB/CC applications are running in Protected Mode, and this uses flat 32-bit addressing.


            Getting back to the real world...

            Yet another way to handle creating arrays in a DLL is to DIM either a STATIC or GLOBAL array in the DLL, and then pass a pointer to the first subscript back to the EXE. Then in the EXE, use the DIM..AT to superimpose an array "over the top" of the DLL's array allocation. See DIM..AT for more information. Note that this is a common way to handle passing arrays from VB to a PowerBASIC DLL, but since your EXE is a PB app, you can use the trick in reverse.

            Very effective, and very fast, since only a pointer is passed. By using DIM..AT, the DLL continues to "own" the array, and the EXE just gains access to the array storage.

            PowerBASIC Support
            mailto:[email protected][email protected]</A>
            mailto:[email protected]


            • #7
              Lance -

              How on earth do I pass the pointer back to the calling EXE???

              Here's an excerpt from my test DLL function DECLARE statement in
              my custom INC file:

              DECLARE...blah, blah...(BYVAL A$, BYVAL B AS STRING PTR)

              Then, in the DLL procedure, I have the following:

              B = VARPTR(Z$(1))

              The DLL compiles fine with that setup. Note that my arguments
              are declared in the procedure's first statement the same as they
              are in the INC file.

              As for the calling EXE, I have the follwoing excerpts:

              GLOBAL wx AS STRING PTR

              Ans& = blah, blah...("c:\pbdll60\samples\bu.rc", @wx)

              If I try to compile the EXE with the last argument as simply wx,
              I get the compiler error message "...string operand expected..."

              If I compile it as given in the excerpt, it compiles, but when I
              try to run the TEST.EXE, I get a GPF error.


              Thanks in advance!

              Clay C. Clear


              [email protected]
              [email protected]


              • #8
                string ptr wx isn't assigned to anything so it will be a null pointer (GPF)

                mailto[email protected][email protected]</A>

                "Simplicity is a prerequisite for reliability"


                • #9
                  The target string must be STATIC or GLOBAL so it stays allocated when then sub/function exits, thus:
                  GLOBAL A$

                  Next, the pointer must point to a valid string handle, and string data should be allocated:
                  A$ = "text"
                  DIM WX AS STRING PTR
                  WX = VARPTR(A$)

                  Now you can return WX to the calling code, or pass it to another sub/function, thus:
                  AnotherString$ = "More " + @WX

                  PowerBASIC Support
                  mailto:[email protected][email protected]</A>
                  mailto:[email protected]