Hello!
The Code below is a FreeBasic routine which produce and returns correct values when run as an EXE, but when the code is
compiled to a DLL file and called from PB, it returns totally different and wrong values(See below).
In PB:
Declare Function FirstBitt Alias "FirstBitt" (Quad)Import "FindFirstBit.dll" As Long
? firstBitt(65280)
? firstBitt(16842752)
? firstbitt(16777216)
? firstbitt(65024)
? firstbitt(33685504)
? firstbitt(64512)
Anyone any idea?
--
Olav
Function FirstBitt CDecl Alias "FirstBitt" (Bittmap As LongInt) As Long Export
'Function FirstBitt (Bittmap As LongInt) As Long ' run as an exe
If Bittmap = 0 Then Exit Function
' De Bruijn Multiplication, see http:'chessprogramming.wikispaces.com/BitScan
' don't use this if bitmap = 0
Dim INDEX64(63) As Long
INDEX64(0) = 63
INDEX64(1) = 0
INDEX64(2) = 58
INDEX64(3) = 1
INDEX64(4) = 59
INDEX64(5) = 47
INDEX64(6) = 53
INDEX64(7) = 2
INDEX64(8) = 60
INDEX64(9) = 39
INDEX64(10) = 48
INDEX64(11) = 27
INDEX64(12) = 54
INDEX64(13) = 33
INDEX64(14) = 42
INDEX64(15) = 3
INDEX64(16) = 61
INDEX64(17) = 51
INDEX64(18) = 37
INDEX64(19) = 40
INDEX64(20) = 49
INDEX64(21) = 18
INDEX64(22) = 28
INDEX64(23) = 20
INDEX64(24) = 55
INDEX64(25) = 30
INDEX64(26) = 34
INDEX64(27) = 11
INDEX64(28) = 43
INDEX64(29) = 14
INDEX64(30) = 22
INDEX64(31) = 4
INDEX64(32) = 62
INDEX64(33) = 57
INDEX64(34) = 46
INDEX64(35) = 52
INDEX64(36) = 38
INDEX64(37) = 26
INDEX64(38) = 32
INDEX64(39) = 41
INDEX64(40) = 50
INDEX64(41) = 36
INDEX64(42) = 17
INDEX64(43) = 19
INDEX64(44) = 29
INDEX64(45) = 10
INDEX64(46) = 13
INDEX64(47) = 21
INDEX64(48) = 56
INDEX64(49) = 45
INDEX64(50) = 25
INDEX64(51) = 31
INDEX64(52) = 35
INDEX64(53) = 16
INDEX64(54) = 9
INDEX64(55) = 12
INDEX64(56) = 44
INDEX64(57) = 24
INDEX64(58) = 15
INDEX64(59) = 8
INDEX64(60) = 23
INDEX64(61) = 7
INDEX64(62) = 6
INDEX64(63) = 5
'65280 bittmap 17137856407927308800 unsigned __int64
'16842752 bittmap 15412894960227319808 unsigned __int64
'16777216 bittmap 16544622118059376640 unsigned __int64
' 65024 bittmap 15828968742145065984 unsigned __int64
'33685504 bittmap 12379045846745088000 unsigned __int64
'64512 bittmap 13211193410580580352 unsigned __int64
Dim DEBRUIJN64 As ULongint
Dim BB As ULongInt
DEBRUIJN64 = &H07EDD5E59A4E28C2
BB = (Bittmap And -Bittmap) * DEBRUIJN64
BB = BB Shr 58
Function = INDEX64(BB)
End Function
' Run as an exe
' Returns as non-dll(Same as in C) ' Called from PB it returns
'Print firstbitt(65280) ' 8 3
'Print firstbitt(16842752) ' 16 2
'Print firstbitt(16777216) ' 24 5
'Print firstbitt(65024) ' 9 2
'Print firstbitt(33685504) ' 17 3
'Print firstbitt(64512) ' 10 2
'Sleep
'End
You are using the CDECL calling convention in the FreeBasic function, but STDCALL in the PB declare.
Use:
Declare Function FirstBitt CDECL Import "FindFirstBit.dll" Alias "FirstBitt" (Bittmap As QUAD) As Long
Quote from: José Roca on November 27, 2012, 06:50:59 PM
You are using the CDECL calling convention in the FreeBasic function, but STDCALL in the PB declare.
Use:
Declare Function FirstBitt CDECL Import "FindFirstBit.dll" Alias "FirstBitt" (Bittmap As QUAD) As Long
Thanks for quick reply, but I'm sorry to say that CDECL didn't work. With this keyword added, the DLL routine returned the value 3 for all of the different input values, shown in the original message.
--
Olav
Probably it is because quads are signed integers and in your FreeBasic code you are using it as if it was unsigned.
Quote from: José Roca on November 27, 2012, 07:41:33 PM
Probably it is because quads are signed integers and in your FreeBasic code you are using it as if it was unsigned.
I have made some changes, but it still returns 3 for all different input values.
I can't quite understand that those unsigned 64 bit variables, local to the function, should affect the function's return
value. Or am I wrong on this?
--
In FreeBasic:
Function FirstBitt CDecl Alias "FirstBitt" (Bittmap As LongInt) As LongInt Export
'LongInt is the same as QUAD in PB
....
....
Function = CLngInt(INDEX64(BB))
In PB:
Declare Function FirstBitt Alias "FirstBitt" (Bittmap As Quad)CDecl, Import "FindFirstBit.dll" As Quad
A bit suprising that PB does not have native support for unsigned 64 bit variables.
--
Olav
Try using an ULARGE_INTEGER structure in your PB declaration:
TYPE ULARGE_INTEGER
LowPart AS DWORD
HighPart AS DWORD
END TYPE
Quote from: José Roca on November 27, 2012, 09:24:20 PM
Try using an ULARGE_INTEGER structure in your PB declaration:
TYPE ULARGE_INTEGER
LowPart AS DWORD
HighPart AS DWORD
END TYPE
Thanks for your suggestion, but I have solved the problem. Just learned that FreeBasic pass parameters BYVAL as
default. So all I had to do was to add a BYVAL to the parameter in the DECLARE statement.
Declare Function FirstBitt Alias "FirstBitt" (ByVal Bittmap As Quad) Import "FindFirstBit.dll" As Quad
Didn't need the CDECL either.
Thanks for your time!
--
Olav
I wonder why they call these compilers BASIC, if they don't follow the rules of the BASIC language.
> Didn't need the CDECL either.
If you FrreeBASIC function uses the CDECL calling convention, you need it; otherwise, the stack won't be cleaned. You must use the same calling convention in the two languages.
Quote from: José Roca on November 28, 2012, 08:29:22 AM
I wonder why they call these compilers BASIC, if they don't follow the rules of the BASIC language.
> Didn't need the CDECL either.
If you FrreeBASIC function uses the CDECL calling convention, you need it; otherwise, the stack won't be cleaned. You must use the same calling convention in the two languages.
Thanks for that information.
BYVAL:
I wouldn't mind if Powerbasic came up with something like #OPTION BYVAL ON, whatever. Think of how much typing one could save(shorter line too), and in addition BYVAL as default would comply with/to the principle that one should use local variables over global ones. BYREF variables is in a way a kind of globals , in my opionion.
--
Olav