Announcement

Collapse
No announcement yet.

Passing an Array

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

  • Passing an Array

    I'm passing a simple 2 dimensional array of numbers from Excel 2003 to/from a PB9 compiled DLL. And I'm doing it with code of the (simplified) form:

    Code:
    Sub Name alias "NAME" (byref y as Long) export
      dim y() as Long
      vbY = vbArrayFirstElement(y)
      redim y(RowLB to RowUB, ColLB to ColUB) as Long at vbY
    All works well. But what I really want to do is pass a Single precision array, not a Long array. So I change a couple of "minor" things as follows:

    Code:
    Sub Name alias "NAME" (byref y as [B]Single[/B]) export
      dim y() as [B]Single[/B]
      vbY = vbArrayFirstElement(y)
      redim y(RowLB to RowUB, ColLB to ColUB) as [B]Single[/B] at vbY
    This crashes Excel every time I try to call it. I assume it's creating the array incorrectly and stomping all over Excel's memory map in some obnoxious way.

    Does anyone recognize what I'm doing wrong here?

    Thanks.

    Bill
    Last edited by William Martin; 23 Apr 2009, 05:13 PM.

  • #2
    >redim y(RowLB to RowUB, ColLB to ColUB) as Long at vbY

    If that works (all values check out), can't just say it's not an array of LONGs, it's an arrray of SINGLEs, you have to copy all the array elements.

    The other things I would look at... if those values do NOT check out as longs...

    - the column, row, precedence of the respective arrays.
    - the LBOUND (is it one? zero? or some other value?)

    FWIW, 'REDIM AT' itself does not touch the memory used by the array elements.

    MCM
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      Oops, missed the obvious..... "BYREF Y AS SINGLE" has a limited precision of 6 decimal digits. If it's an address, use a LONG or a DWORD.

      MCM
      Michael Mattias
      Tal Systems (retired)
      Port Washington WI USA
      [email protected]
      http://www.talsystems.com

      Comment


      • #4
        Originally posted by Michael Mattias View Post
        Oops, missed the obvious..... "BYREF Y AS SINGLE" has a limited precision of 6 decimal digits. If it's an address, use a LONG or a DWORD.
        That does in fact fix my problem. This seemed wrong to me because now I tell the Excel routine that the variable is typed as Single, but tell PB that it's typed as DWORD. But ... it works!

        Thanks for your help.

        Bill

        Comment


        • #5
          I am a little surprised it fixed it as well, your sub in PB should be
          Sub Name alias "NAME" (BYVAL y as DWORD) export
          and in VBA as Sub Name alias "NAME" (byref y as Single)
          and when called in VBA Name thisarray(0) assuming the array was defined as singles. Note the BYVAL, as the the variable was passed BYREF then the Y in PB is just receiving the address

          Comment


          • #6
            Note the BYVAL, as the the variable was passed BYREF then the Y in PB is just receiving the address
            ???

            Um, references to any variable (eg "Y") in any statement (eg 'REDIM AT') implicitly mean "the value of variable" and the the compiler deferences addresses when necessary.... like, when it has been told that parameter was passed by reference.

            ???

            However, the code making the call is not shown, so we cannot possibly know if the "Y" parameter to the procedure "NAME" (using a reserved word as a procedure name? Maybe it's OK, but, Yechhh!) should be defined in the procedure header by reference or by value.

            MCM
            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #7
              Originally posted by Michael Mattias View Post
              ???

              Um, references to any variable (eg "Y") in any statement (eg 'REDIM AT') implicitly mean "the value of variable" and the the compiler deferences addresses when necessary.... like, when it has been told that parameter was passed by reference.

              ???

              MCM
              Then he would have had to have been passing an address for y to contain it byref, not easy to do from VBA, normally you pass the first element of the array BYREF with its proper type and in PB receive the address of that into a variable using BYVAL and then DIM AT that address, though this requires passing the bounds of the array as well. If he was not sending an address then changing y to a long makes no sense. However he includes another function vbArrayFirstElement which I am not familiar with to get that address. If as his question implies he is passing the first value of the array as a byref single then the receiving sub must also be looking for a byref single and its address be determined by some other means such as VARPTR. From my PB manual "The most common use of an absolute array is when manipulating Visual Basic arrays directly from a DLL. This involves obtaining a pointer to the array, the element size, and the number of elements." which is exactly what I showed and have used for many years.
              As you said we need the other half of the code.
              Last edited by John Petty; 24 Apr 2009, 11:37 AM.

              Comment


              • #8
                As I mentioned, my problem is solved. Just to complete the discussion however here's simplified code of the Excel/VBA end of the system in hopes it may help someone else later. I was remiss not to provide it originally:

                Code:
                Option Base 0
                Declare Sub Name Lib "PB9.Compiled.DLL" Alias "NAME" (ByRef Y() As Single)
                
                Sub Call_DLL( )
                  ...
                  ReDim Y(LastRow, LastCol) As Single
                  ...
                  Call Name(Y())
                  ...
                End Sub
                Thanks for the help.

                Bill

                Comment


                • #9
                  Bill
                  Your declare in VBA clarifies the situation. When you pass an entire Array in that way PB receives the address of the array descriptor which stricly should be a BYREF DWORD though a LONG should suffice. You then determine the address of the first element using vbArrayFirstElem to know where to DIM AT.
                  The other method is to just in the VBA declare have a simple SINGLE variable BYREF and in PB receive it as BYVAL DWORD which is the address you DIM AT, of course with this method you need to pass the Bounds as well.
                  John

                  Comment

                  Working...
                  X