Announcement

Collapse
No announcement yet.

Exported PB function in DLL - how to call from VB

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

  • Exported PB function in DLL - how to call from VB

    Here is the PB function being exported:
    Code:
    FUNCTION CRC32HASH (BYVAL ptrBuffer AS DWORD, BYVAL lenBuffer AS LONG, szReturn AS LONG) EXPORT AS LONG
    Here is how I call it in Powerbasic:
    Code:
    #COMPILE EXE
    #INCLUDE "win32api.inc"
     
    DECLARE FUNCTION CRC32HASH Lib "crc32.dll" ALIAS "CRC32HASH" (BYVAL ptrBuffer AS DWORD, BYVAL lenBuffer AS LONG, szReturn AS LONG) AS LONG
     
    FUNCTION PBMAIN() AS LONG
    ON ERROR RESUME NEXT
    Dim MyString As String
    Dim ResultCrc AS Long
    MyString = "Test" & CHR$(0) & "Test"
    Dim Result AS LONG
    Result = CRC32HASH(STRPTR(MyString), LEN(MyString), ResultCrc)
    MSGBOX "Result=" & STR$(Result) & ", CRC=" & HEX$(ResultCrc)   'Should return 45862144
    END FUNCTION
    I need to also call it from Visual Basic, does anyone know how ?


    [This message has been edited by Wayne Diamond (edited September 15, 2001).]
    -

  • #2
    Guess, that BYVAL ptrBuffer AS DWORD here is equal ByVal Buffer As String

    ------------------
    E-MAIL: [email protected]

    Comment


    • #3
      You can call it from VB
      FUNCTION CRC32HASH (BYVAL ptrBuffer AS any, BYVAL lenBuffer AS LONG, szReturn AS LONG) AS LONG

      You'll have to play with it to get the type's correct...ptrBuffer may have to be a string


      But not as an exe

      Change to:

      #COMPILE dll


      Haven't tried it but it should work

      Doug

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


      [This message has been edited by D. McDonald (edited September 15, 2001).]
      Doug McDonald
      KD5NWK
      www.redforksoftware.com

      Comment


      • #4
        Nope! Thanks very much Semen and D McDonald, but I still haven't got it working yet! I've tried all sorts of variations... here is what I've been able to get it up to:
        Code:
        [b]Private Declare Function CRC32HASH Lib "crc32.dll" (ByVal ptrBuffer As Long, ByVal lenBuffer As Long, szReturn As Long) As Long[/b]
        Private Declare Function lstrcpy Lib "kernel32.dll" (ByVal lpString1 As Any, ByVal lpString2 As Any) As Long
          
        Public Function PointerToString(lPtr As Long) As String
        On Error Resume Next
        Dim sTemp As String * 255, Retval As Long
            Retval = lstrcpy(sTemp, lPtr)
            If (InStr(1, sTemp, Chr(0)) = 0) Then
                 PointerToString = ""
            Else
                 PointerToString = Left$(sTemp, InStr(1, sTemp, Chr(0)) - 1)
            End If
        End Function
          
        Private Sub Form_Load()
        On Error Resume Next
        If Dir$(App.Path & "\CRC32.dll") = "" Then
           MsgBox "CRC32.dll must be in " & App.Path & "!", vbExclamation + vbOKOnly, "DLL not found"
           End
        End If
        Dim TestString As String
        Dim ReturnPtr As Long
        Dim CRCResult As Long
        TestString = "Test" & Chr$(0) & "Test"
        [b]CRCResult = CRC32HASH(ByVal TestString, ByVal Len(TestString), ReturnPtr)[/b]
        If CRCResult = 1 Then
           MsgBox "String=" & PointerToString(ReturnPtr), , "ReturnPtr=" & CStr(ReturnPtr)
        Else
           MsgBox "CRC32 call failed!"
        End If
        End
        End Sub
        That always returns "String=" (and then no string), but the title is "ReturnPtr=" and then a huge number, indicating it had successfully received an address..?
        The key to solving this is assumingly in the two lines ive highlighted in bold, but Ive tried all sorts of combinations of longs, anys, strings, byvals etc without any luck The DLL definately works fine because I can call it from Powerbasic and lcc-win32 fine, just not VB but thats where I need to call it from now!


        [This message has been edited by Wayne Diamond (edited September 16, 2001).]
        -

        Comment


        • #5
          Here is CRC32.BAS - what i am trying to call -- basically, I just need to make crc32.bas friendly with all languages (which im pretty sure it already is?), and by "friendly", i mean it has to be able to accept strings with CHR$(0)'s in them (so im using a test string of <U>"Test" & Chr$(0) & "Test"</U>, which should return a CRC32 value of 45862144 -- which it does if you use the above PB calltest.bas)
          Im pretty sure there doesn't need to be any modifications to CRC32.DLL because I think its already about as 'friendly' as it can get with all languages?

          Code:
          #COMPILE DLL "crc32.dll"
          #REGISTER NONE
          #INCLUDE "WIN32API.INC"
          
          GLOBAL DLLhInst AS LONG
            
          FUNCTION LibMain(BYVAL hInstance   AS LONG, _
                           BYVAL fwdReason   AS LONG, _
                           BYVAL lpvReserved AS LONG) EXPORT AS LONG
            SELECT CASE fwdReason
              CASE %DLL_PROCESS_ATTACH
                 DLLhInst = hInstance
                 LibMain = 1   'success!
                EXIT FUNCTION
              CASE %DLL_PROCESS_DETACH
                 LibMain = 1   'success!
                EXIT FUNCTION
              CASE %DLL_THREAD_ATTACH
                 LibMain = 1   'success!
                EXIT FUNCTION
              CASE %DLL_THREAD_DETACH
                 LibMain = 1   'success!
              EXIT FUNCTION
             END SELECT
          END FUNCTION
          
          FUNCTION Crc32(BYVAL Address AS DWORD, _
                         BYVAL Length AS LONG, _
                         BYVAL Seed AS LONG) AS LONG
            ! push    EBX                     ; save EBX for PowerBASIC
            ! push    EDI                     ; save EDI for PowerBASIC
            ! mov     EDI,Address             ; address in EDI
            ! mov     ECX,Length              ; length in ECX
            ! jecxz   CrcDone                 ; exit is zero length
            ! cld                             ; clear the direction flag
          BuildCRC:
            ! movzx   EBX, Byte Ptr [EDI]     ; get a char
            ! mov     AX, Seed[1]             ; get 2nd and 3rd bytes of seed
            ! xor     DX, DX                  ; clear DX
            ! mov     DL, Seed[3]             ; get 4th byte of seed
            ! xor     BL, Seed[0]             ; xor char against first byte of seed
            ! xor     BH, BH                  ; clear BH
            ! shl     BX, 2                   ; shift the index
            ! xor     AX, CrcTable[EBX]       ; xor low-half against the table
            ! xor     DX, CrcTable[EBX+2]     ; xor high-half against the table
            ! mov     Seed[0], AX             ; save the result
            ! mov     Seed[2], DX             ;   ...
            ! inc     EDI                     ; move to next char
            ! loop    BuildCRC                ; do ECX times
          CrcDone:
            ! pop     EDI                     ; restore EDI
            ! pop     EBX                     ; restore EBX
            FUNCTION = Seed
            EXIT FUNCTION
          CrcTable:
            ! dd &H000000000&, &H077073096&, &H0EE0E612C&, &H0990951BA&
            ! dd &H0076DC419&, &H0706AF48F&, &H0E963A535&, &H09E6495A3&
            ! dd &H00EDB8832&, &H079DCB8A4&, &H0E0D5E91E&, &H097D2D988&
            ! dd &H009B64C2B&, &H07EB17CBD&, &H0E7B82D07&, &H090BF1D91&
            ! dd &H01DB71064&, &H06AB020F2&, &H0F3B97148&, &H084BE41DE&
            ! dd &H01ADAD47D&, &H06DDDE4EB&, &H0F4D4B551&, &H083D385C7&
            ! dd &H0136C9856&, &H0646BA8C0&, &H0FD62F97A&, &H08A65C9EC&
            ! dd &H014015C4F&, &H063066CD9&, &H0FA0F3D63&, &H08D080DF5&
            ! dd &H03B6E20C8&, &H04C69105E&, &H0D56041E4&, &H0A2677172&
            ! dd &H03C03E4D1&, &H04B04D447&, &H0D20D85FD&, &H0A50AB56B&
            ! dd &H035B5A8FA&, &H042B2986C&, &H0DBBBC9D6&, &H0ACBCF940&
            ! dd &H032D86CE3&, &H045DF5C75&, &H0DCD60DCF&, &H0ABD13D59&
            ! dd &H026D930AC&, &H051DE003A&, &H0C8D75180&, &H0BFD06116&
            ! dd &H021B4F4B5&, &H056B3C423&, &H0CFBA9599&, &H0B8BDA50F&
            ! dd &H02802B89E&, &H05F058808&, &H0C60CD9B2&, &H0B10BE924&
            ! dd &H02F6F7C87&, &H058684C11&, &H0C1611DAB&, &H0B6662D3D&
            ! dd &H076DC4190&, &H001DB7106&, &H098D220BC&, &H0EFD5102A&
            ! dd &H071B18589&, &H006B6B51F&, &H09FBFE4A5&, &H0E8B8D433&
            ! dd &H07807C9A2&, &H00F00F934&, &H09609A88E&, &H0E10E9818&
            ! dd &H07F6A0DBB&, &H0086D3D2D&, &H091646C97&, &H0E6635C01&
            ! dd &H06B6B51F4&, &H01C6C6162&, &H0856530D8&, &H0F262004E&
            ! dd &H06C0695ED&, &H01B01A57B&, &H08208F4C1&, &H0F50FC457&
            ! dd &H065B0D9C6&, &H012B7E950&, &H08BBEB8EA&, &H0FCB9887C&
            ! dd &H062DD1DDF&, &H015DA2D49&, &H08CD37CF3&, &H0FBD44C65&
            ! dd &H04DB26158&, &H03AB551CE&, &H0A3BC0074&, &H0D4BB30E2&
            ! dd &H04ADFA541&, &H03DD895D7&, &H0A4D1C46D&, &H0D3D6F4FB&
            ! dd &H04369E96A&, &H0346ED9FC&, &H0AD678846&, &H0DA60B8D0&
            ! dd &H044042D73&, &H033031DE5&, &H0AA0A4C5F&, &H0DD0D7CC9&
            ! dd &H05005713C&, &H0270241AA&, &H0BE0B1010&, &H0C90C2086&
            ! dd &H05768B525&, &H0206F85B3&, &H0B966D409&, &H0CE61E49F&
            ! dd &H05EDEF90E&, &H029D9C998&, &H0B0D09822&, &H0C7D7A8B4&
            ! dd &H059B33D17&, &H02EB40D81&, &H0B7BD5C3B&, &H0C0BA6CAD&
            ! dd &H0EDB88320&, &H09ABFB3B6&, &H003B6E20C&, &H074B1D29A&
            ! dd &H0EAD54739&, &H09DD277AF&, &H004DB2615&, &H073DC1683&
            ! dd &H0E3630B12&, &H094643B84&, &H00D6D6A3E&, &H07A6A5AA8&
            ! dd &H0E40ECF0B&, &H09309FF9D&, &H00A00AE27&, &H07D079EB1&
            ! dd &H0F00F9344&, &H08708A3D2&, &H01E01F268&, &H06906C2FE&
            ! dd &H0F762575D&, &H0806567CB&, &H0196C3671&, &H06E6B06E7&
            ! dd &H0FED41B76&, &H089D32BE0&, &H010DA7A5A&, &H067DD4ACC&
            ! dd &H0F9B9DF6F&, &H08EBEEFF9&, &H017B7BE43&, &H060B08ED5&
            ! dd &H0D6D6A3E8&, &H0A1D1937E&, &H038D8C2C4&, &H04FDFF252&
            ! dd &H0D1BB67F1&, &H0A6BC5767&, &H03FB506DD&, &H048B2364B&
            ! dd &H0D80D2BDA&, &H0AF0A1B4C&, &H036034AF6&, &H041047A60&
            ! dd &H0DF60EFC3&, &H0A867DF55&, &H0316E8EEF&, &H04669BE79&
            ! dd &H0CB61B38C&, &H0BC66831A&, &H0256FD2A0&, &H05268E236&
            ! dd &H0CC0C7795&, &H0BB0B4703&, &H0220216B9&, &H05505262F&
            ! dd &H0C5BA3BBE&, &H0B2BD0B28&, &H02BB45A92&, &H05CB36A04&
            ! dd &H0C2D7FFA7&, &H0B5D0CF31&, &H02CD99E8B&, &H05BDEAE1D&
            ! dd &H09B64C2B0&, &H0EC63F226&, &H0756AA39C&, &H0026D930A&
            ! dd &H09C0906A9&, &H0EB0E363F&, &H072076785&, &H005005713&
            ! dd &H095BF4A82&, &H0E2B87A14&, &H07BB12BAE&, &H00CB61B38&
            ! dd &H092D28E9B&, &H0E5D5BE0D&, &H07CDCEFB7&, &H00BDBDF21&
            ! dd &H086D3D2D4&, &H0F1D4E242&, &H068DDB3F8&, &H01FDA836E&
            ! dd &H081BE16CD&, &H0F6B9265B&, &H06FB077E1&, &H018B74777&
            ! dd &H088085AE6&, &H0FF0F6A70&, &H066063BCA&, &H011010B5C&
            ! dd &H08F659EFF&, &H0F862AE69&, &H0616BFFD3&, &H0166CCF45&
            ! dd &H0A00AE278&, &H0D70DD2EE&, &H04E048354&, &H03903B3C2&
            ! dd &H0A7672661&, &H0D06016F7&, &H04969474D&, &H03E6E77DB&
            ! dd &H0AED16A4A&, &H0D9D65ADC&, &H040DF0B66&, &H037D83BF0&
            ! dd &H0A9BCAE53&, &H0DEBB9EC5&, &H047B2CF7F&, &H030B5FFE9&
            ! dd &H0BDBDF21C&, &H0CABAC28A&, &H053B39330&, &H024B4A3A6&
            ! dd &H0BAD03605&, &H0CDD70693&, &H054DE5729&, &H023D967BF&
            ! dd &H0B3667A2E&, &H0C4614AB8&, &H05D681B02&, &H02A6F2B94&
            ! dd &H0B40BBE37&, &H0C30C8EA1&, &H05A05DF1B&, &H02D02EF8D&
          END FUNCTION
            
          FUNCTION CRC32HASH (BYVAL ptrBuffer AS DWORD, BYVAL lenBuffer AS LONG, szReturn AS LONG) EXPORT AS LONG
          ON ERROR RESUME NEXT
          DIM I AS LONG
          DIM Result AS LONG
          LOCAL CRC AS LONG
          CRC = CRC32(BYVAL ptrBuffer, BYVAL lenBuffer, -1)
          CRC = CRC XOR -1&
          szReturn = CRC
          FUNCTION = 1
          END FUNCTION

          [This message has been edited by Wayne Diamond (edited September 16, 2001).]
          -

          Comment


          • #6
            Problem solved by none other than Semen
            Code:
            Private Declare Function CRC32HASH Lib "crc32.dll" (ByVal Buffer As String, ByVal lenBuffer As Long, szReturn As Long) As Long
                              
            Private Sub Form_Load()
               a$ = "Test" + Chr$(0) + "Test"
               CRC32HASH a$, Len(a$), Rz&
               MsgBox Hex$(Rz&)
               End
            End Sub
            Too easy!


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

            Comment


            • #7
              Delphi expert needed!
              I don't understand why this doesn't work - it sends the string "Test" & Chr$(0) & "Test" to the crc32.dll fine, and also the length was parsed fine - 9 bytes, but the result being returned is always this:
              xRet=2147348480
              The CRC32 checksum is: 7FFDF000
              it says that regardless of what data you send it! It doesnt make much sense to me, but here is how Im calling it from Delphi:
              Code:
              {$APPTYPE CONSOLE}
              {$X+}
              program CallCRC32;
              uses
                SysUtils,
                Windows;
               
              Type
                String8 = String[8];
               
              Function CRC32HASH(  strBuffer: String; strReturnBuffer: LongInt; lReturn: LongInt): LongInt;
               stdcall; external 'CRC32.DLL';
               
              Var
                CRCStr : String8;
                S: String;
                xRet: LongInt;
               
              Procedure LongToHex(AnyLong : LongInt; Var HexString : String8);
              Var
                ch    : Char;
                Index : Byte;
              begin
                HexString := '00000000';                  { default to zero   }
                Index := Length(HexString);               { String length     }
                While AnyLong <> 0 do
                begin                                     { loop 'til done    }
                  ch := Chr(48 + Byte(AnyLong) and $0F);  { 0..9 -> '0'..'9'  }
                  if ch > '9' then
                    Inc(ch, 7);                           { 10..15 -> 'A'..'F'}
                  HexString[Index] := ch;                 { insert Char       }
                  Dec(Index);                             { adjust chr Index  }
                  AnyLong := AnyLong SHR 4;               { For next nibble   }
                end;
              end;
               
              begin
              // SetLength(S, 9);
               S := 'Test' + Chr(0) + 'Test';
               if CRC32HASH( S, 9, xRet) = 1
                  then begin
                    LongToHex(xRet, CRCStr);
                    writeln('xRet=',IntToStr(xRet));
                    writeln('The CRC32 checksum is: ', CRCStr)
                  end
               else begin
                  writeln('CRC call failed!');
               end;
              end.

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

              Comment


              • #8
                89 wouldve been the last time i used pascal too! But with this bit:
                Code:
                 S := 'Test' + Chr(0) + 'Test';
                 if CRC32HASH( S, 9, xRet) = 1
                    then begin
                      LongToHex(xRet, CRCStr);
                      writeln('xRet=',IntToStr(xRet));
                      writeln('The CRC32 checksum is: ', CRCStr)
                    end
                 else begin
                    writeln('CRC call failed!');
                 end;
                S only holds 'Test'+chr(0)+'Test'
                xRet is filled with a longint that is the resulting CRC (before conversion to hex)
                CRCStr is filled in by the LongToHex function
                or am i not understanding your post correctly?


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

                Comment


                • #9
                  I saw that, Wayne and killed the message. Try casting 'S' with PChar:
                  if CRC32HASH( PChar(S), 9, xRet) = 1

                  Comment


                  • #10
                    hrm nope, PChar(S) and S are both having the same effect, but that doesnt appear to be a problem because crc32.dll is definately receiving the first two parameters (buffer and bufferlength) with no problems
                    Interestingly, when I compile, a warning is given about xRet possibly not being initialised. If I do initialise it (eg. xRet := 0; ), the program crashes when it tries to call the DLL. If I leave it uninitialised, it always returns 7FFDF000 regardless of what string it received. The problem seems to be in the last parameter of the function - the one that RECEIVES a long integer value from the DLL (as opposed to the first two parameters which it is sending), so i think thats the key?


                    [This message has been edited by Wayne Diamond (edited September 16, 2001).]
                    -

                    Comment


                    • #11
                      Function CRC32HASH( strBuffer: String; strReturnBuffer: LongInt; VAR lReturn: LongInt): LongInt; stdcall; external 'CRC32.DLL';

                      ------------------
                      Tom Hanlin
                      PowerBASIC Staff

                      Comment


                      • #12
                        Tom, youre the man!!! My Pascal books dont mention that, so seemingly var in that sense is native to Delphi. I did a quick google search and found mention of this "where the keyword var has been used to indicate the argument is passed by reference." - exactly what I needed
                        Thankyou kind sir
                        PS. just putting this C++ version here for my own benefit when I search for it in POFFS next month -
                        "Pass-by-reference in C++ is achieved by placing an ampersand before the parameter identifier in the function header"
                        e.g.: void validswap(int &x, int &y)
                        Good info on this at http://www.ece.purdue.edu/~eigenman/EE462/QandA.html and http://engr.uark.edu/~wessels/lang/spring00/cpp.html


                        [This message has been edited by Wayne Diamond (edited September 17, 2001).]
                        -

                        Comment


                        • #13
                          Glad I could help. FWIW, "VAR" is standard Pascal, meaning the same as BYREF
                          in BASIC. Unlike BASIC, Pascal passes parameters BYVAL by default...

                          ------------------
                          Tom Hanlin
                          PowerBASIC Staff

                          Comment

                          Working...
                          X