Announcement

Collapse
No announcement yet.

Problem calling PB DLLs from VB

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

  • Problem calling PB DLLs from VB

    Hi All,

    I am trying to write a series of DLLs to be called by VB 2008 apps as well as VBA code in Excel and Access. I have had some success but I have been unable to pass any more than one variable to a function in a DLL. If I try to pass more than one then VB6/VBA just crashes and VB2008 gives the error message "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

    I have tried every possible combination of passing variables ByVal and ByRef. The DLLs work fine when called from a PB application.

    I have got to a stage where I need to emulate some legacy functions that pass variables as ByRef arrays. Here is an example of the DLL code:
    ----------------------
    #COMPILE DLL
    #DIM ALL
    %USEMACROS = 1
    #INCLUDE "Win32API.inc"
    FUNCTION BRfunc ALIAS "BRfunc"(BYREF Int0 AS INTEGER, BYREF Arr1() AS BYTE, BYREF Arr2() AS STRING, BYREF Int1 AS INTEGER) EXPORT AS LONG
    DIM i AS INTEGER
    DIM tStr AS STRING
    FOR i = 0 TO Int0
    tStr = Arr2(i)
    Arr2(i) = STR$(arr1(i)) & " " & tStr
    NEXT
    Int1 = i-1
    FUNCTION = i
    END FUNCTION
    ------------------------------------
    And here is the Powerbasic code that calls it:
    ------------------------------------
    #COMPILE EXE
    #DIM ALL
    DECLARE FUNCTION BRfunc LIB "ByRefDll.dll" ALIAS "BRfunc" (BYREF Int0 AS INTEGER, BYREF Arr1() AS BYTE, BYREF Arr2() AS STRING, BYREF Int1 AS INTEGER) AS LONG
    FUNCTION PBMAIN () AS LONG
    DIM Rint AS INTEGER
    DIM Rlng AS LONG
    DIM Rstr AS STRING
    DIM i AS INTEGER
    DIM AnimalQty(5) AS BYTE
    DIM AnimalName(5) AS STRING
    AnimalQty(0) = 5
    AnimalName(0) = "snakes"
    AnimalQty(1) = 3
    AnimalName(1) = "emus"
    AnimalQty(2) = 23
    AnimalName(2) = "sheep"
    AnimalQty(3) = 202
    AnimalName(3) = "caterpillars"
    AnimalQty(4) = 7
    AnimalName(4) = "elephants"
    AnimalQty(5) = 2
    AnimalName(5) = "horses"
    Rlng = BRfunc(5, AnimalQty(), AnimalName(), Rint)
    Rstr = STR$(Rlng) & " types of animals:"
    FOR i = 0 TO Rint
    Rstr = Rstr & CHR$(13) & AnimalName(i)
    NEXT
    MSGBOX Rstr
    END FUNCTION
    ----------------------------------
    This works fine in PowerBasic. The same code in any VB does not work. Attached are some code examples in VB6 and VB 2008 that demonstrate the problem.

    Can anyone please let me know where I am going wrong.

    Thanks in advance,

    Rob
    Attached Files

  • #2
    Not sure how byte arrays are passed, but this how string arrays are passed.
    See page 634 of manual on SafeArrays

    Here is the bulletin board codes for posting code:
    http://www.powerbasic.com/support/pb....php?do=bbcode
    It is also at the bottom of the page under BB code

    The word "code" within brackets to start a code block, /code within brackets to end code block.




    Code:
    #INCLUDE "Win32API.inc"
    #INCLUDE "VBAPI32.INC" 
     
    FUNCTION BRfunc ALIAS "BRfunc"(Int0 AS INTEGER,  Arr1() AS BYTE,  pSA AS DWORD,  Int1 AS INTEGER) EXPORT AS LONG
     
      DIM i AS LONG
      DIM tStr AS STRING
     
      LOCAL l AS LONG
      LOCAL u AS LONG
      LOCAL vb AS DWORD
      l  = vbArrayLBound(psa,1)
      u  = vbArrayUBound(psa,1)
      vb = vbArrayFirstElem(psa)
      DIM arr2(l TO u) AS STRING AT VB
     
      FOR i = l TO u
        tStr = Arr2(i)
        Arr2(i) = "Not sure here" + STR$(i)
       NEXT
       Int1 = i-1
     
      FUNCTION = i
    END FUNCTION
    Last edited by Mike Doty; 12 Jul 2009, 03:14 AM. Reason: Show how to post code
    How long is an idea? Write it down.

    Comment


    • #3
      All arrays in VB are SafeArrays which is not the PB default, they can be read in PB a couple of different ways. The STRING array has an additional problem in that the strings will/may be in Unicode again not a PB default. I add the word "may" as in some cases VB6 (haven't used 8) will attempt ,not always successfully, to convert to ANSII strings from Unicode i.e if you have an array of fixed length strings inside a UDT it would convert only the first array member.

      Comment


      • #4
        Thanks

        Thanks for the replies. After a couple of tries I was able to do what I need. The array of strings are not required. I tried it because I had previously struck problems passing string variables. This application requires arrays of unsigned integers so the example on page 634 showed the way.

        I had not got as far as Appendix B on page 632 of the manual. It explains the problems I was having.

        Lets see if I get this right:
        Code:
        #COMPILE DLL
        #DIM ALL
        FUNCTION BRfunc ALIAS "BRfunc"(BYVAL Arr1 AS DWORD, BYVAL Arr2 AS DWORD, BYVAL Int0 AS LONG) EXPORT AS LONG
        DIM Brr1(Int0) AS LONG AT Arr1
        DIM Brr2(Int0) AS LONG AT Arr2
        DIM i AS LONG
        DIM j AS LONG
        DIM k AS LONG
            FOR i = 0 TO Int0
                j = Brr2(i) * Brr1(i)
                Brr1(i) = j
                k = k + j
            NEXT
            FUNCTION = k
        END FUNCTION
        Thanks again,

        Rob

        Comment


        • #5
          If Int0 is the number of elements of the array, it should be:

          Code:
          #COMPILE DLL
          #DIM ALL
          FUNCTION BRfunc ALIAS "BRfunc"(BYVAL Arr1 AS DWORD, BYVAL Arr2 AS DWORD, BYVAL Int0 AS LONG) EXPORT AS LONG
          DIM Brr1(Int0-1) AS LONG AT Arr1
          DIM Brr2(Int0-1) AS LONG AT Arr2
          DIM i AS LONG
          DIM j AS LONG
          DIM k AS LONG
              FOR i = 0 TO Int0-1
                  j = Brr2(i) * Brr1(i)
                  Brr1(i) = j
                  k = k + j
              NEXT
              FUNCTION = k
          END FUNCTION
          Forum: http://www.jose.it-berater.org/smfforum/index.php

          Comment


          • #6
            Thanks again

            Thanks José. I had better do as you suggest in order to reduce confusion. That is a similar convention to some other DLLs I work with.

            Regards,

            Rob

            Comment

            Working...
            X