Page 1 of 1
Problem using PB64 with 3rd Party 64-bit App
Posted: Sat Jun 09, 2012 3:24 pm
by TeraByte
I wrote the following simple 64 bit DLL and am unable to get it to work with a 3rd party application called Multicharts64. The problem seems to be when I try to return a double or float. I'm using PB64 v4.61.
Code: Select all
EnableExplicit
; These 4 procedures are Windows specific
;
; This procedure is called once, when the program loads the library
; for the first time. All init stuffs can be done here (but not DirectX init)
;
ProcedureDLL AttachProcess(Instance)
EndProcedure
; Called when the program release (free) the DLL
;
ProcedureDLL DetachProcess(Instance)
EndProcedure
; Both are called when a thread in a program call or release (free) the DLL
;
ProcedureDLL AttachThread(Instance)
EndProcedure
ProcedureDLL DetachThread(Instance)
EndProcedure
;
; Real code start here..
;
ProcedureDLL.l AddLong(num1.l, num2.l)
Protected Mysum.l
Mysum = num1 + num2
ProcedureReturn Mysum
EndProcedure
ProcedureDLL.f AddFloat(num1.f, num2.f)
Protected Mysum.f
Mysum = num1 + num2
ProcedureReturn Mysum
EndProcedure
ProcedureDLL.d AddDouble(num1.d, num2.d)
Protected Mysum.d
Mysum = num1 + num2
ProcedureReturn Mysum
EndProcedure
ProcedureDLL.i AddInt(num1.i, num2.i)
Protected Mysum.i
Mysum = num1 + num2
ProcedureReturn Mysum
EndProcedure
ProcedureDLL Mult2xRefFloat(*num1.Float, *num2.Float)
*num1\f = (*num1\f) * 2.0
*num2\f = (*num2\f) * 2.0
EndProcedure
ProcedureDLL Mult2xRefDouble(*num1.Double, *num2.Double)
*num1\d = (*num1\d) * 2.0
*num2\d = (*num2\d) * 2.0
EndProcedure
The following procedures work fine: AddLong, AddInt, Mult2xRefFloat and Mult2xRefDouble.
PROBLEM:
The following procedures FAIL: AddFloat, and AddDouble
AddFloat(3.14, 2.15) returns: 3.14 rather than 5.29
AddDouble(4.14, 5.15) returns: 4.14 rather than 9.29
The 3rd Party app Multicharts support staff say the problem is something in my PB DLL64.
I would really appreciate your experts insight. Have I done something wrong in the PB code? Thank you.
Re: Problem using PB64 with 3rd Party 64-bit App
Posted: Sat Jun 09, 2012 3:42 pm
by srod
My guess would be that the 3rd party app is not expecting that floating point returns are placed on the floating point stack (which is where PB leaves them).
I've seen something like this before.
Try the following :
Code: Select all
ProcedureDLL.l AddFloat(num1.f, num2.f)
Protected Mysum.f
Mysum = num1 + num2
ProcedureReturn PeekL(@Mysum)
EndProcedure
Re: Problem using PB64 with 3rd Party 64-bit App
Posted: Sat Jun 09, 2012 7:27 pm
by TeraByte
Thanks srod for the suggestion. Unfortunately, it did not work. Here's the snippet of modified code. I put in your changes and also output some info to a log file:
Code: Select all
ProcedureDLL.f AddFloat(num1.f, num2.f)
Protected Mysum.f
Mysum = num1 + num2
CompilerIf #DebugLog=1
PrintToFile("v20120609-1417 AddFloat:" + StrF(Num1) + " + " + StrF(Num2) + " = " + StrF(mysum) + ", PeekL=" + Str(PeekL(@MySum)))
CompilerEndIf
ProcedureReturn PeekL(@Mysum)
EndProcedure
ProcedureDLL.d AddDouble(num1.d, num2.d)
Protected Mysum.d
Mysum = num1 + num2
CompilerIf #DebugLog=1
PrintToFile("AddDouble:" + StrD(Num1) + " + " + StrD(Num2) + " = " + StrD(mysum) + ", PeekL=" + Str(PeekL(@MySum)))
CompilerEndIf
ProcedureReturn PeekL(@Mysum)
EndProcedure
Here's the output file:
v20120609-1417 AddFloat:3.1400001049 + 2.1500000954 = 5.2899999619, PeekL=1084835758
14:19:26:: AddDouble:4.1400000000 + 5.1500000000 = NaN, PeekL=0
So the AddFloat is computing the correct sum, but the 3rd party app is returning a zero.
The AddDouble is receiving the correct numbers to add, but the sum is NaN.
This doesn't make sense. I hope some expert can figure out this oddity.
Re: Problem using PB64 with 3rd Party 64-bit App
Posted: Sat Jun 09, 2012 8:23 pm
by srod
You haven't copied my code correctly.
Code: Select all
ProcedureDLL.l AddFloat(num1.f, num2.f)
Protected Mysum.f
Mysum = num1 + num2
ProcedureReturn PeekL(@Mysum)
EndProcedure
ProcedureDLL.l not .f !!!
Re: Problem using PB64 with 3rd Party 64-bit App
Posted: Sat Jun 09, 2012 9:35 pm
by TeraByte
Hi srod, thanks for your correction. Now I have it exactly like yours. The output from 3rd party app is "0". Here is the output from the log file:
2012-06-09, 16:27:59:: v20120609-1424 AddFloat:3.1400001049 + 2.1500000954 = 5.2899999619, PeekL=1084835758
Code: Select all
EnableExplicit
#DebugLog = 1 ; Off=0, On=1
Procedure PrintToFile( MyOut.s)
Define Tempstr.s
Define FileNum.l
FileNum = OpenFile (#PB_Any,"c:\IEC_Log.txt")
If FileNum > 0
FileSeek(FileNum, Lof(FileNum))
Tempstr= FormatDate("%yyyy-%mm-%dd, %hh:%ii:%ss:", Date() ) + ": " + MyOut
WriteStringN(FileNum, Tempstr)
CloseFile(FileNum)
EndIf
CompilerIf #DebugLog
OutputDebugString_("PrintToFile: " + Tempstr)
CompilerEndIf
EndProcedure
;
; These 4 procedures are Windows specific
;
; This procedure is called once, when the program loads the library
; for the first time. All init stuffs can be done here (but not DirectX init)
;
ProcedureDLL AttachProcess(Instance)
EndProcedure
; Called when the program release (free) the DLL
;
ProcedureDLL DetachProcess(Instance)
EndProcedure
; Both are called when a thread in a program call or release (free) the DLL
;
ProcedureDLL AttachThread(Instance)
EndProcedure
ProcedureDLL DetachThread(Instance)
EndProcedure
;
; Real code start here..
;
ProcedureDLL.l AddLong(num1.l, num2.l)
Protected Mysum.l
Mysum = num1 + num2
ProcedureReturn Mysum
EndProcedure
ProcedureDLL.l AddFloat(num1.f, num2.f)
Protected Mysum.f
Mysum = num1 + num2
CompilerIf #DebugLog=1
PrintToFile("v20120609-1424 AddFloat:" + StrF(Num1) + " + " + StrF(Num2) + " = " + StrF(mysum) + ", PeekL=" + Str(PeekL(@MySum)))
CompilerEndIf
ProcedureReturn PeekL(@Mysum)
EndProcedure
ProcedureDLL.d AddDouble(num1.d, num2.d)
Protected Mysum.d
Mysum = num1 + num2
ProcedureReturn Mysum
EndProcedure
ProcedureDLL.i AddInt(num1.i, num2.i)
Protected Mysum.i
Mysum = num1 + num2
ProcedureReturn Mysum
EndProcedure
ProcedureDLL Mult2xRefFloat(*num1.Float, *num2.Float)
*num1\f = (*num1\f) * 2.0
*num2\f = (*num2\f) * 2.0
EndProcedure
ProcedureDLL Mult2xRefDouble(*num1.Double, *num2.Double)
*num1\d = (*num1\d) * 2.0
*num2\d = (*num2\d) * 2.0
EndProcedure
Re: Problem using PB64 with 3rd Party 64-bit App
Posted: Sat Jun 09, 2012 9:42 pm
by TeraByte
As another quick test, I tried the following code which returns "112596307.00"
Code: Select all
ProcedureDLL.d ReturnDouble()
ProcedureReturn 7.123
EndProcedure
Re: Problem using PB64 with 3rd Party 64-bit App
Posted: Sat Jun 09, 2012 9:49 pm
by srod
Ok, I still think that the problem is that the float is being returned in a way which the 3rd party app is not expecting. Perhaps, the return is expected to be placed in one of the registers such as RDX as opposed to the top of the fp stack?
What does the documentation say regarding the use of your dll? Is it perhaps expecting a pointer return instead?
Re: Problem using PB64 with 3rd Party 64-bit App
Posted: Sun Jun 10, 2012 7:16 am
by Helle
The 3rd party app expect the result in register xmm0 (standard for 64-bit float/double-procedures).
Try this:
Code: Select all
;For Test
TestFloat.f
TestDouble.d
ProcedureDLL.f AddFloat(num1.f, num2.f) ;num1=XMM0, num2=XMM1
Shared MysumF.f ;!
MysumF = num1 + num2
!MOVSS XMM0,[v_MysumF]
EndProcedure
;or simple
ProcedureDLL.f AddFloat3rdparty(num1.f, num2.f) ;num1=XMM0, num2=XMM1
!ADDSS XMM0,XMM1
EndProcedure
ProcedureDLL.d AddDouble(num1.d, num2.d) ;num1=XMM0, num2=XMM1
Shared MysumD.d ;!
MysumD = num1 + num2
!MOVSD XMM0,[v_MysumD]
EndProcedure
;or simple
ProcedureDLL.d AddDouble3rdparty(num1.d, num2.d) ;num1=XMM0, num2=XMM1
!ADDSD XMM0,XMM1
EndProcedure
;Test
AddFloat(3.14, 2.15)
!MOVSS [v_TestFloat],XMM0
Debug TestFloat
AddFloat3rdparty(3.14, 2.15)
!MOVSS [v_TestFloat],XMM0
Debug TestFloat
AddDouble(4.14, 5.15)
!MOVSD [v_TestDouble],XMM0
Debug TestDouble
AddDouble3rdparty(4.14, 5.15)
!MOVSD [v_TestDouble],XMM0
Debug TestDouble
Note: Debug destroy register XMM0 (if you make tests)!
Have fun!
Helle
Re: Problem using PB64 with 3rd Party 64-bit App
Posted: Sun Jun 10, 2012 11:51 am
by srod
Ah, I don't know enough about x64 asm code, but at least we were on the right track; the only possible explanation really.
Let's hope that does the trick.
Re: Problem using PB64 with 3rd Party 64-bit App
Posted: Sun Jun 10, 2012 4:58 pm
by c4s
...Isn't it a bug then?
Re: Problem using PB64 with 3rd Party 64-bit App
Posted: Sun Jun 10, 2012 5:03 pm
by DarkDragon
c4s wrote:...Isn't it a bug then?
No, compatibility to other languages was never a big official feature of purebasic.
Re: Problem using PB64 with 3rd Party 64-bit App
Posted: Sun Jun 10, 2012 7:43 pm
by xorc1zt
the code
Code: Select all
ProcedureDLL.f Return_float()
ProcedureReturn 8.55
EndProcedure
ProcedureDLL.d Return_double()
ProcedureReturn 8.55
EndProcedure
produce
Code: Select all
.code:0000000180001084 ; Exported entry 1. Return_double
.code:0000000180001084
.code:0000000180001084 ; =============== S U B R O U T I N E =======================================
.code:0000000180001084
.code:0000000180001084
.code:0000000180001084 public Return_double
.code:0000000180001084 Return_double proc near
.code:0000000180001084 sub rsp, 28h
.code:0000000180001088 fld cs:dbl_180004014 ; 8.550000000000001
.code:000000018000108E jmp short loc_180001092
.code:0000000180001090 fldz
.code:0000000180001092 loc_180001092:
.code:0000000180001092 add rsp, 28h
.code:0000000180001096 retn
.code:0000000180001096 Return_double endp
.code:0000000180001096
.code:0000000180001097 ; Exported entry 2. Return_float
.code:0000000180001097
.code:0000000180001097 ; =============== S U B R O U T I N E =======================================
.code:0000000180001097
.code:0000000180001097
.code:0000000180001097 public Return_float
.code:0000000180001097 Return_float proc near
.code:0000000180001097 sub rsp, 28h
.code:000000018000109B fld cs:flt_180004010 ; 8.5500002
.code:00000001800010A1 movsxd rax, eax
.code:00000001800010A4 jmp short loc_1800010A8
.code:00000001800010A6 fldz
.code:00000001800010A8 loc_1800010A8:
.code:00000001800010A8 add rsp, 28h
.code:00000001800010AC retn
.code:00000001800010AC Return_float endp
.code:00000001800010AC
why fldz ?