No announcement yet.

VB and PowerBasic DLLs

  • Filter
  • Time
  • Show
Clear All
new posts

  • VB and PowerBasic DLLs


    I'm new to PB and I'm having terrible trouble with GPFs in my DLL's when I call them from VB6.

    For example, I have a DLL written in PB called ENCRYPT defined in PB as follows:


    In VB6 this is declared as:

    Declare Function ENCRYPT Lib "SVE.DLL" (ByVal str_type As String, ByVal str_input As String, ByVal str_key As String) As String

    The problem I have is that when I call the function from VB is works sometime, GPS's sometime and gives the wrong result other times. It also seem to change the value of the paramaters to incomprehensible values.

    The function works fine when I call it from a PowerBasic EXE.

    Can anyone tell me what I'm doing wrong?

    Mark Jarzebowski
    Melbourne, Australia
    [email protected]

  • #2
    Hi Mark,
    This is from the PBDLL 6.0 helpfile (Appendix B):

    Many API calls require ASCIIZ, or nul-terminated strings. Visual Basic does not natively support this data-type, so it relies on a “kludge” to pass the correct data. To pass an ASCIIZ string, you add the ByVal keyword to the Declare statement or Call,

    Call PowerBasicDll(ByVal MyString$)

    Visual Basic converts the data in MyString$ to ANSI format with a nul (or CHR$(0)) appended to the end of it, and passes a memory address to the location of the string data. PowerBASIC does natively support ASCIIZ string, so the ByVal keyword is not used:

    SUB PowerBasicDll(MyString AS ASCIIZ) EXPORT

    REPLACE "the" WITH "The" in MyString


    If the called API or DLL modifies the data, it can not extend the length past that of the data it received, or a GPF may occur. If the modified data is shorter than the original string passed, the Visual Basic code must “fix” the string’s length by extracting all characters up to the CHR$(0) embedded in the string data.

    It is also important to note that a string ByVal in PowerBASIC is not the same thing as a string ByVal in Visual Basic. That is, since PowerBASIC natively supports ASCIIZ strings, it does not convert a dynamic string into an ASCIIZ string, as does Visual Basic. PowerBASIC does what you tell it, it makes a copy of the string and passes the new string handle to the API or DLL. If you have the following Declare statement in Visual Basic,

    Private Declare Sub Hello Lib "HELLO.DLL" (ByVal Greetings$)

    You should remove the ByVal and convert the string to ASCIIZ when Declaring the same Sub in PowerBASIC:


    Hope this helps

    The most exasperating part of the "rat race" is how often the rats are in the lead!


    • #3

      I would expand the syntax up to a complete PowerBASIC function declaration
      as follows. I think you may have trouble with VB when you attempt to pass
      the string "ByVal". The format below uses the "ALIAS" to make the function
      name case sensitive which is normal for DLLs. This is because basic is not
      case sensitive where DLLs in te system must be.

      str_input AS STRING, _

      I am years out of date with VB but the idea is to ensure that your declaration
      matches the format that you have used in your DLL.

      Good luck with it.

      [email protected]

      hutch at movsd dot com
      The MASM Forum - SLL Modules and PB Libraries


      • #4
        Thanks for your susggestions guys.

        I'll give them a try.

        Mark Jarzebowski
        Melbourne, Australia
        [email protected]


        • #5

          VB handles strings differently than PB does !

          VB uses OLE strings (for variable length). It uses the OLE engine in Windows. PB does too, but ...

          While in PB you can pass strings using BYVAL and they are still the same type (OLE), VB does a fudge factor.

          In VB:

          If you pass a string using BYVAL, VB will convert the string to AsciiZ (null terminated string similiar to C strings). Your PB DLL must use AsciiZ strings to receive a string passed using BYVAL from VB.

          If you pass a string BYREF (by reference), then VB will pass the string as an OLE string (uses the OLE engine). This means your PB DLL functions must use BYREF to match it. If your PB function defines the string parameter as BYVAL, it will cause problems in this case.

          On another note, VB stores all strings as Unicode strings internally, but when they are passed to an external procedure (in a DLL) , VB converts them to Ansi (uses standard ascii codes with one byte per character) before passing them to your DLL. This is good because PB only uses Ansi strings. This doesn't affect your using PB for DLLs, but it will affect the "speed" of functions that are called many times in a loop. Since VB must convert strings from Unicode to Ansi and then back again when the DLL call returns, it adds a lot of extra CPU cycles to the function call. Passing strings in a fixed len string may be faster in some instances.

          Chris Boss
          Computer Workshop
          Developer of "EZGUI"


          • #6
            Here's a sample I did a while back, works well and can't show you the function itself but that's OK.

            Declare Function ParseEmailFile (FileSpec As String, _
                                    psaInfoData  As Dword, _
                                    psaInfoQty   As Dword, _
                                    psaInfoProdName As Dword, _
                                    psaInfoAmt   As Dword, _
                                    ArrayCount As Long) As Long 
            Function ParseEmailFile  (FileSpec As String, _
                                    psaInfoData  As Dword, _
                                    psaInfoQty   As Dword, _
                                    psaInfoProdName As Dword, _
                                    psaInfoAmt   As Dword, _
                                    ArrayCount As Long) Export As Long 
            'Notice the DWORD, this is for passing arrays, by reference and not by value...
            '--convert pInfoData SafeArray To PB-Array--------
            lower&  = vbArrayLBound(psaInfoData, 1)
            upper&  = vbArrayUBound(psaInfoData, 1)
            vbArray = vbArrayFirstElem(psaInfoData)
            Dim pInfoData(lower& To upper&) As String At vbArray    
            'Now do this for each array value passed...
            Now if any of this holds true for strings without arrays, i'm not sure, but I would think so..
            The calling VBCode:
            Public pInfoData() As String
            Public pInfoQty() As String
            Public pInfoProdName() As String
            Public pInfoAmt() As String
            Public ArrayCount As Long
            Global St As String
            Public Declare Function ParseEmailFile Lib "MAILP.DLL" Alias "PARSEEMAILFILE" _
                                    (FileSpec As String, _
                                    pInfoData() As String, _
                                    pInfoQty() As String, _
                                    pInfoProdName() As String, _
                                    pInfoAmt() As String, ArrayCount As Long) As Long    
            'In the form load or wh erever:
            private Result as long
                Result = ParseEmailFile(FileSpec, pInfoData(), pInfoQty(), pInfoProdName(), pInfoAmt(), ArrayCount)

            mailto:[email protected][email protected]</A>
            Scott Turchin
            MCSE, MCP+I
            True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi