Page 1 of 1

DLL needs DOUBLE Values

Posted: Fri Aug 29, 2003 7:56 am
by clipper
Hallo there,

I´m calling a DLL from PureBasic with
CallFunction(#DLL,"SetDimensions",100,200)
the values 100 and 200 must be given as DOUBLE Values.
How can I do that ?
The declaration of this function in Visual Basic is:
Public Declare Function SetDimensions Lib "derly.dll" (ByVal PageWidth As Double, ByVal PageHeight As Double) As Long

Thank´s a lot for your attention

Posted: Fri Aug 29, 2003 8:11 am
by plouf
have you try this one ?

Code: Select all

structure Double
  Hi.l
  Lo.l
endstructure 

Var1.double 
Var1\Lo = 100
VAr2.double
Var2\Lo = 200

CallFunction(#DLL,"SetDimensions",Var1,Var2) 
[\code]

Posted: Fri Aug 29, 2003 8:35 am
by clipper
I've tried your code but it will not work.
DOUBLE is here a 8Byte float from
-1.79769313486232E308 to -4.94065645841247E-324
other functions without DOUBLE of this dll working fine.
I´ve tested the DLL with VB - everything works fine.

Posted: Fri Aug 29, 2003 12:35 pm
by jack
try this and see if it works.

Code: Select all

Structure double
  a.l
  b.l
EndStructure

Procedure LtoDouble(x.l,*y.double)
! fild dword [esp]
! mov ebx,[esp+4]
! fstp qword [ebx]
EndProcedure

Procedure FtoDouble(x.f,*y.double)
! fld dword [esp]
! mov ebx,[esp+4]
! fstp qword [ebx]
endprocedure
then

Code: Select all

x.double
y.double
LtoDouble(100,@x)
LtoDouble(200,@y)
CallFunction(#DLL,"SetDimensions",x,y)

Posted: Fri Aug 29, 2003 1:16 pm
by freak
> Public Declare Function SetDimensions Lib "derly.dll" (ByVal PageWidth As Double, ByVal PageHeight As Double) As Long

The double values need to be passed 'ByVal', this means, the actual value
needs to be passed as argument, not the pointer to the value (which would
be 'ByRef')
Passing a structure to a function in PB always passes the pointer, not the
structure itself.

So the call in jacks example should maybe look like this:

Code: Select all

CallFunction(#DLL,"SetDimensions",x\b, x\a, y\b, y\a) 
So the full value goes on the stack. I'm not quite sure about the order
though. maybe the '\a' and '\b' values need to be changed.

I'm not quite sure about this myself. So if jack's code doesn't work, just
give it a try :wink:

Timo

Posted: Sat Aug 30, 2003 12:23 pm
by VPureBasic
Hi All,

Here a code you should try:

Code: Select all

Structure d
       HiValue.l
       LoValue.l
EndStructure

Deftype X.d
Deftype Y.d

Procedure MakeDoubleInteger( LONG.l, ADDRESS.l )
       !FILD   dword [ Esp ]                ; Load integer value
       !MOV   dword Eax, [ Esp + 4 ]   ; Get the address
       !FISTP  qword [ Eax ]               ; Save as double value
EndProcedure

MakeDouble( 100, @X )
MakeDouble( 200, @Y )
CallFunction( #DLL,"SetDimensions", X\HiValue,X\LoValue,   Y\HiValue,Y\LoValue )

Roger

Posted: Sat Aug 30, 2003 2:51 pm
by jack
VPureBasic, the DLL is expecting a double, not an integer.
by executing fistp you are storing the value as integer, not double.

Longs serve for DoubleWords

Posted: Sat Aug 30, 2003 7:46 pm
by oldefoxx
Long are the same size as doublewords, but the uppermost bit is a signed value. That just means that for very loarge values, you have to pass it as a negative value instead of a positive one. You can also define the parameters for the DLL function as having two words passed in place of each double word. The DLL does not know how you declare its functions, nor does it care, just as long as it gets the right values in the right places on the stack when called. So your only concern is to pass the upper and lower word values in the right sequence.

To show you what happens when you use a long, I wrote this little routine to print out an abbreviated power table, where longs are converted into the two word values.

Code: Select all

;Two's Table Generator
;by Donald Darden

;Gives table of powers of 2 for longs And how they translate into dual word
;(doubleword) representations.


OpenConsole()
consolecolor(15,1)
ClearConsole()
a.w=0
b.w=0
c.l=1
x$=""
ConsoleLocate(2,2)
PrintN("Read Table as long = lower, upper word:")
ConsoleLocate(0,4)
Repeat
  MOV eax,c                       ;move variable c into the eax register
  PUSH eax                        ;save it for later  
  MOV a,ax                        ;copy the lower word into variable a 
  ROR eax,16                      ;rotate to get upper eax word into ax reg
  MOV b,ax                        ;save the upper word into variable b 
  x$+"  "+Str(c)+" = "+Str(a.w)+", "+Str(b.w)  ;build the output string
  If Len(x$)>40                   ;see if time to print yet  
    PrintN(x$)                    ;yes, print string 
    x$=""                         ;start string over  
  Else
    x$+Space(40-Len(x$))          ;no, keep building string 
  EndIf
  POP eax                         ;get back original variable c 
  ROL eax,1                       ;rotate it left 1 bit (rotates around)  
  MOV c,eax                       ;save it as the new value for variable c  
Until c=1                         ;see if we have rotated around yet
If x$>""                          ;make sure we print last line
  PrintN(x$)
EndIf  
PrintN("")
PrintN("  Note that word variables are unsigned, so the display of -32768 in the")
PrintN("  above table would be incorrect, and apparently reflects a bug in the")
PrintN("  way PureBasic displays word values.")
Repeat:Until Inkey()>""          ;wait for a key press to end  
CloseConsole()
End

Posted: Sat Aug 30, 2003 7:58 pm
by VPureBasic
Hi,
jack wrote:VPureBasic, the DLL is expecting a double, not an integer.
by executing fistp you are storing the value as integer, not double.
I screwed up for FISTP instead of FSTP... anyways... That's only a mistake about a letter... The code is good if you take it off...


Roger

Posted: Sat Aug 30, 2003 9:41 pm
by jack
incredible!, you take away the 'i' and you have exactly
what i already posted, don't see the point.

Posted: Sun Aug 31, 2003 12:57 am
by VPureBasic
Hi Jack,
jack wrote:incredible!, you take away the 'i' and you have exactly
what i already posted, don't see the point.
Did you read what you code:

Code: Select all

CallFunction(#DLL,"SetDimensions",x,y) 
And I:

Code: Select all

CallFunction( #DLL,"SetDimensions", X\HiValue,X\LoValue,   Y\HiValue,Y\LoValue )
Are you blind are what?!?! Can you see the point this time... We are here to help peoples with their problems not to push people away with sarcasim answer!!!

I do not give advices or tips very often on this forum because of people like U! Thanks to remember me to stay annonymous...

Roger

Posted: Mon Sep 01, 2003 7:25 am
by clipper
Yeeees ! Thanks a lot for your help !!

the working code I use now is listen above.
the DLL-output is ok if I use Values like '100'
I can´t use floats like '100.41'



==8<----------------------
Structure double
Hi.l
Lo.l
EndStructure

Procedure MakeDouble( LONG.l, ADDRESS.l )
!FILD dword [ Esp ]
!MOV dword Eax, [ Esp + 4 ]
!FSTP qword [ Eax ]
EndProcedure

Var1.double
Var2.double

MakeDouble( 100, @Var1 )
MakeDouble( 200, @Var2 )

CallFunction(#DLL,"SetDimensions",Var1\Hi,Var1\Lo,Var2\Hi,Var2\Lo )
==8<----------------------

Posted: Mon Sep 01, 2003 7:30 am
by Pupil
clipper wrote:Yeeees ! Thanks a lot for your help !!

the working code I use now is listen above.
the DLL-output is ok if I use Values like '100'
I can´t use floats like '100.41'
Remove the 'i' in the FILD command and it'll work with floats ;) By doing this the procedure will not produce valid results for long type variables, so you have to go with the two procedures that jack posted earlier, i.e. one procedure for each variable type...

Posted: Mon Sep 01, 2003 12:37 pm
by VPureBasic
Hi clipper,
clipper wrote:Yeeees ! Thanks a lot for your help !!

the working code I use now is listen above.
the DLL-output is ok if I use Values like '100'
I can´t use floats like '100.41'
Just change "LONG.l" to "FLOAT.f" here:
Procedure MakeDoubleFloat( FLOAT.f, ADDRESS.l )
...
...
...
EndProcedure
Roger

Posted: Mon Sep 01, 2003 1:45 pm
by clipper
:D Many thanks to all coders!
Now it works great and I my DLL eats every value I give her