Announcement

Collapse
No announcement yet.

Windows error when calling a DLL created by PBDLL 6 from Visual Basic 6.0 SP3.

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

    Windows error when calling a DLL created by PBDLL 6 from Visual Basic 6.0 SP3.

    I'm trying to use a PowerBasic DLL I created with PBDLL 6 in Visual Basic 6.0 SP3. It errors out after calling the DLL function two or three times. The windows error and the VB & PB code is shown below. I would really appreciate some advice.

    Thanks, Ron Weber
    Code:
    ======================================================
    Windows 98 - 4.10.1998 - error:
    
    This program has performed an illegal operation
    and will be shut down.
    
    If the problem persists, contact the program vendor.
    
    VB6 caused an invalid page fault in
    module KERNEL32.DLL at 0177:bff7a4a3.
    
    Registers:
    EAX=00000018 CS=0177 EIP=bff7a4a3 EFLGS=00010206
    EBX=00000002 SS=017f ESP=007fe7f0 EBP=007fe800
    ECX=005d0008 DS=017f ESI=005d0000 FS=4b4f
    EDX=00000020 ES=017f EDI=005d000c GS=0000
    
    Bytes at CS:EIP:
    8b 03 25 fc ff ff 0f 3b 45 0c 0f 83 81 00 00 00 
    
    Stack dump:
    0000001a 7ff527a8 00000000 881a47df 
    007fe814 bff88d9b 005d0000 00000020 
    00000000 007fe86c 7ff314f0 005d0000 
    00000000 0000001a 7ff31520 7ffdd00c 
    
    ======================================================
    Visual Basic 6.0 - SP3 - Module1.bas:
    
    ' DataCenter database record.
    Type DataCenterDB
        VarTable As String * 6
        VarName As String * 100
        VarValue As String * 10000
    End Type
    
    Declare Function GetVar Lib "DC.DLL" Alias "GETVAR" (ByVal x As String, ByVal y As String, ByVal z As String) As String
    
    ======================================================
    Visual Basic 6.0 - SP3 - frmCreate.bas:
    
    Private Sub cmdGetRecord_Click()
    
        Dim p As String
        Dim t As String
        Dim n As String
        Dim v As String
        
        p = "D:\SIMPLE COMPUTER SOLUTIONS\Software Products\VB 6.0\DataCenter\PowerTree"
        
        t = "IN"
        
        n = "VAR-48884.4"
        
        v = GetVar(p, t, n)
        
        MsgBox v
        
    End Sub
    
    ======================================================
    PBDLL 6 - DC.DLL
    
    #COMPILE DLL
    
    #INCLUDE "*********"
    
    TYPE DataCenterDB
        VarTable AS STRING * 6
        VarName AS STRING * 100
        VarValue AS STRING * 10000
    END TYPE
    
    FUNCTION GetVar (BYVAL pname AS STRING, BYVAL t AS STRING, BYVAL n AS STRING) EXPORT AS STRING
    
        ON ERROR GOTO Error_Routine
    
        CLOSE
    
        DIM hFile    AS LONG          ' data file handle
        DIM rec AS DataCenterDB       ' data file record
        DIM recs     AS LONG          ' count of records in data file
        DIM KeyBlock AS ***********   ' index file information
        DIM combo    AS STRING * 106  ' combined 'Table' and 'DataName'
        DIM tout     AS LONG
        DIM e AS STRING
    
        IF pname <> "" AND RIGHT$(pname,1) <> "\" THEN pname = pname + "\"
    
        ' Open the data file
    Open_DB:
        hFile = FREEFILE
        tout = 0
    Open_Again:
        ERRCLEAR
        e = "OPEN"
        OPEN pname + "DataCenter.DB" FOR RANDOM LOCK READ WRITE AS hFile LEN = LEN(rec)
        e = ""
        IF ERR THEN
            GetVar = "Error - Unable to open data file DataCenter.DB"
            EXIT FUNCTION
        END IF
    
        ' Get the total number of records in the file and check for sanity.
        recs = LOF(hFile) \ LEN(rec)
        IF recs * LEN(rec) <> LOF(hFile) THEN
            GetVar = "Error - Corrupt data file DataCenter.DB (bad record length)"
            EXIT FUNCTION
        END IF
    
        ' Store Table and Data Name into 'rec' variable.
        rec.VarTable = UCASE$(t)
        rec.VarName = UCASE$(n)
        combo = rec.VarTable + rec.VarName
    
        ' Initialize index.
        ************************
        **********************
        *****************************************
        IF **************** <> 0 THEN
            GetVar = "Error - Could not initialize DataCenter.PTX"
            EXIT FUNCTION
        END IF
    
        ' See if Data Name already exists.
        ********************
    
        ' Get record.
        IF **************** = 0 THEN
    
            tout = 0
            e = "GET"
            GET hFile, KeyBlock.RecordNumber, rec
            e = ""
    
            GetVar = TRIM$(rec.VarValue)
    
        ELSE
    
            MSGBOX "Variable Not Found"
    
        END IF
    
        ****************
    
        CLOSE hFile
    
        EXIT FUNCTION
    
    Error_Routine:
    
        IF e = "OPEN" AND tout < 30000 THEN
            tout = tout + 1
            RESUME Open_Again
        END IF
        IF e = "GET" AND tout < 30000 THEN
            tout = tout + 1
            CLOSE hFile
            RESUME Open_DB
        END IF
    
        CLOSE
    
    END FUNCTION
    ------------------

    #2
    After briefly looking over your code I didn't see anything that
    stood out. Have you tried this on another machine? Or have you
    tried calling the DLL from an external PB/DLL (.exe) program?

    The symptoms might be machine dependant.

    I didn't have a chance to try and compile your code but when I do
    I'll try.



    ------------------
    -Greg
    -Greg
    [email protected]
    MCP,MCSA,MCSE,MCSD

    Comment


      #3
      Hi Ronald,
      You might try getting rid of "ByVal" in your VB declaration and in
      your PB Function Statement. Refer to Appendix B of your PB help.

      FUNCTION GetVar (pname AS STRING, t AS STRING, n AS STRING) EXPORT AS STRING
      Declare Function GetVar Lib "DC.DLL" Alias "GETVAR" (x As String, y As String, z As String) As String

      Hope that fixes it for you.


      ------------------
      [email protected]

      Comment


        #4
        When VB passes a dynamic string BYVAL to a DLL, it does things very differently when compared to how it does it when passing a string to a VB sub/function.

        Essentially, passing a dynamic string BYVAL from VB to a DLL instructs VB to transparently convert the string from Unicode into nul-terminated ANSI string format, and then the address is passed to the DLL. Therefore, the DLL will receive a 32-bit pointer to a nul-terminated string. In PB, a nul-terminated string is known as an ASCIIZ string.

        Therefore, you can retain your existing VB declaration, but change the PB function prototype code to look like this:

        ' PB code:
        FUNCTION GetVar (pname AS ASCIIZ, t AS ASCIIZ, n AS ASCIIZ) EXPORT AS STRING
        ...
        END FUNCTION

        For more information on passing strings between VB and PB/DLL, please consult Appendix B in the documentation.

        There is at least one other problem in the PB code... there are a number of places where EXIT FUNCTION are used without first closing all open files.

        However, to start debugging your code, you'll have to narrow down the exact point at which it fails... one way is to liberally use MSGBOX's in the DLL code to track the progress of the code as it is executed. Another way is to open a 'LOG' file (for append) and write data into the file to track variable values, etc. Either way is useful to track down the cause of the problem.

        Please try these things out and if you still get stuck, let us know.


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

        Comment


          #5
          Wyman, I removed the ByVal statements as you suggested and it seems to be working just fine.

          Lance & Wyman, I didn't relize that there was an appendix devoted to VB. I'm sure that will cover most problems I encounter in the future when using VB and PB together.

          Thanks to everyone for taking the time to help me with my problem.

          Take Care, Ron

          ------------------

          Comment


            #6
            Hi Again Ronald,
            Glad it's working!! Um, just one other thing? You VB black belts
            correct me if I'm wrong, but using the ByRef technique means that
            anything you do to those strings in PB code is going to show up
            on the VB side too. Lance's method passes copies which
            you can abuse to your heart's content and won't affect the VB
            strings. The ByVal = Asciiz conversion is one of Microsoft's
            crueler practical jokes.....lol
            Good Luck!!!

            ------------------
            [email protected]

            [This message has been edited by Wyman A Belts (edited July 06, 2000).]

            Comment


              #7
              Hi,

              Ronald, you could also do your VB Code like this if you
              wish:

              Type DataCenterDB
              VarTable As String * 6
              VarName As String * 100
              VarValue As String * 10000
              End Type

              Declare Function GetVar Lib "DC.DLL" Alias "GETVAR" _
              (ByRef x As DataCenterDB) As String

              ......more code

              and in PowerBasic your function would like:

              #COMPILE DLL "DC.DLL"
              #INCLUDE "PTREE.INC"

              TYPE DataCenterDB
              VarTable AS STRING * 6
              VarName AS STRING * 100
              VarValue AS STRING * 10000
              END TYPE

              FUNCTION GetVar (x AS DataCenterDB) EXPORT AS STRING

              LOCAL pname as string

              pname = x.VarName

              ...........more code

              Just wanted to let you know, because record-sets can get
              very large, and just passing the type is much easier!

              ------------------
              mwm
              mwm

              Comment


                #8
                Wyman - According to the VB docs the ByRef does exaclty what your saying. I'm looking forward to the day when I earn a black belt in PowerBasic and can throw VB in the trash. Until then, I'll just have to use VB and PB together. Are there any training courses I could take for PB and Windows programming? What books are available to get me on the right track?

                Michael - I was under the impression that the PowerTree include file couldn't be posted. From now on I'll eliminate all PowerTree code from my posts. Sorry!!!

                Take Care, Ron

                ------------------

                Comment


                  #9

                  Wyman, you are absolutely right!

                  The ByVal is VB is a joke and a pain!
                  It you're gonna use VB with PB, then use ByRef with all strings.
                  If there's concerns about verifying string etc... it should be
                  noted that if you're programming, then you should be checking
                  everything anyway.

                  Enjoyed your comments Wyman!
                  That's my .02 worth.

                  Ronald, my comments were meant to be kind (not harsh).
                  FYI - in the past, I've seen other's use code similar
                  and since PTree is a dll, we're not suppose to include any
                  code that has PTree function calls within them.
                  (we are suppose to use email support)

                  Thanks
                  Mike




                  ------------------
                  mwm
                  mwm

                  Comment


                    #10
                    Michael,

                    I didn't take your comment as harsh. I appreciate the fact that you let me know what I did so I can post my code correctly next time.

                    Thanks, Ron

                    ------------------

                    Comment

                    Working...
                    X
                    😀
                    🥰
                    🤢
                    😎
                    😡
                    👍
                    👎