Announcement

Collapse
No announcement yet.

Exported PB function in DLL - how to call from VB

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

  • Tom Hanlin
    replied
    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

    Leave a comment:


  • Wayne Diamond
    replied
    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).]

    Leave a comment:


  • Tom Hanlin
    replied
    Function CRC32HASH( strBuffer: String; strReturnBuffer: LongInt; VAR lReturn: LongInt): LongInt; stdcall; external 'CRC32.DLL';

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

    Leave a comment:


  • Wayne Diamond
    replied
    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).]

    Leave a comment:


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

    Leave a comment:


  • Wayne Diamond
    replied
    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?


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

    Leave a comment:


  • Wayne Diamond
    replied
    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.

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

    Leave a comment:


  • Wayne Diamond
    replied
    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!


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

    Leave a comment:


  • Wayne Diamond
    replied
    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).]

    Leave a comment:


  • Wayne Diamond
    replied
    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).]

    Leave a comment:


  • Doug McDonald
    replied
    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).]

    Leave a comment:


  • Semen Matusovski
    replied
    Guess, that BYVAL ptrBuffer AS DWORD here is equal ByVal Buffer As String

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

    Leave a comment:


  • 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).]
Working...
X