Opened 13 years ago
Closed 13 years ago
#2015 closed Bug (Fixed)
DllCallbackRegister() mangles floating point numbers under x64
Reported by: | wraithdu | Owned by: | trancexx |
---|---|---|---|
Milestone: | 3.3.9.0 | Component: | AutoIt |
Version: | 3.3.7.15 | Severity: | None |
Keywords: | dllcallbackregister x64 float | Cc: |
Description (last modified by Valik)
Parameters of type "float" are mangled when passed to DllCallbackRegister() callback functions under x64. The following script demonstrates the problem:
Local $hCallback = DllCallbackRegister("Callback", "none", "double;float;") Local $pCallback = DllCallbackGetPtr($hCallback) DLLCallAddress("none", $pCallback, "double", 1234, "float", 1234) Func Callback($fDouble, $fFloat) ConsoleWrite("Double: " & $fDouble & @CRLF) ConsoleWrite("Float: " & $fFloat & @CRLF) EndFunc
The double output is correct. Float output is mangled and changes with each invocation.
Attachments (0)
Change History (5)
comment:1 Changed 13 years ago by anonymous
comment:2 Changed 13 years ago by Valik
- Description modified (diff)
- Keywords dllcallbackregister added; dllcalladdress removed
- Summary changed from DllCallAddress Corrupts float Type under x64 to DllCallbackRegister() mangles floating point numbers under x64
This is NOT a problem with DllCall() or DllCallAddress(). This is a bug with DllCallbackRegister(). I'm changing the description accordingly. The example script I am going to add is representative of a way to reproduce the problem. I have confirmed with my own DLL that DllCall() does not corrupt the data.
comment:3 Changed 13 years ago by anonymous
Valik, either you didn't test this thoroughly or DLLCall() and DLLCallAddress() use different code for 'float' types? I've verified independently that AutoIt's 'callback' code works perfectly fine when called via alternate means (in my case, 'DispCallFunc'). The float retains its original value in x64 mode. The focus should really be on DLLCallAddress and how floats are passed along.
comment:4 Changed 13 years ago by Valik
I'm not really interested in your independent verifications when mine prove otherwise. I'm also rather annoyed that you think I did something super-complex for DllCallAddress() and that it JUST HAS to be that function. If you spent 3 seconds of thinking about it you would realize all I did was swap out the LoadLibrary() -> GetProcAddress() sequence for explicitly calling the passed address.
Since you seem to not accept that maybe I know how to test a bug, here's the AutoIt code:
#include <WinAPI.au3> Local $sDll If @AutoItX64 Then $sDll = "C:\Data\My Programs\C++\DllTest\x64\Debug\DllTest.dll" Else $sDll = "C:\Data\My Programs\C++\DllTest\Debug\DllTest.dll" EndIf ; Normal DllCall() ConsoleWrite("DllCall(): ") DllCall($sDll, "none", "Test", "double", 1234, "float", 1234) ; Emulate DllCall() ConsoleWrite("DllCallAddress(): ") Local $hDll = _WinAPI_LoadLibrary($sDll) Local $aRet = DllCall("kernel32.dll", "ptr", "GetProcAddress", "handle", $hDll, "str", "Test") DllCallAddress("none", $aRet[0], "double", 1234, "float", 1234) _WinAPI_FreeLibrary($hDll) ; Setup the callback. Local $hCallback,$pCallback $hCallback=DllCallbackRegister("_TestDirectCall","none","double;float") $pCallback=DllCallbackGetPtr($hCallback) ; Invoke the callback via DllCallAddress() ConsoleWrite("Callback (via DllCallAddress()): ") DllCallAddress("none", $pCallback, "double", 1234, "float", 1234) ; Invoke the callback by letting a C function call it. ConsoleWrite("Callback: ") DllCall($sDll, "none", "Test2", "ptr", $pCallback) Func _TestDirectCall($iVar1, $var2) ConsoleWrite("AutoIt - Double: " & $iVar1 & ", AutoIt - Float: " & $var2 & @CRLF) EndFunc ; _TestDirectCall()
And the DLL code:
#include <iostream> typedef void (WINAPI *LPTESTFUNC)(double, float); void WINAPI Test(double d, float f) { std::cout<<"Double: "<<d<<std::endl; std::cout<<"Float: "<<f<<std::endl; } void WINAPI Test2(LPTESTFUNC lpFunc) { lpFunc(1234.0, 1234.0f); }
Module definition file for the DLL:
LIBRARY EXPORTS Test Test2
x86 output with beta 3.3.7.17:
>Running C:\Program Files (x86)\AutoIt3\Beta\AutoIt3.exe (Beta - 3.3.7.17) DllCall(): C++ - Double: 1234, C++ - Float: 1234 DllCallAddress(): C++ - Double: 1234, C++ - Float: 1234 Callback (via DllCallAddress()): AutoIt - Double: 1234, AutoIt - Float: 1234 Callback: AutoIt - Double: 1234, AutoIt - Float: 1234 >Exit code: 0 Time: 0.427
x64 output with beta 3.3.7.17:
DllCall(): C++ - Double: 1234, C++ - Float: 1234 DllCallAddress(): C++ - Double: 1234, C++ - Float: 1234 Callback (via DllCallAddress()): AutoIt - Double: 1234, AutoIt - Float: 1.40129846432482e-045 Callback: AutoIt - Double: 2.75222232409741e-317, AutoIt - Float: 7.617839605252e-039
Happy now Ascend4nt? Was that thorough enough for you?
comment:5 Changed 13 years ago by trancexx
- Milestone set to 3.3.9.0
- Owner set to trancexx
- Resolution set to Fixed
- Status changed from new to closed
Fixed by revision [6588] in version: 3.3.9.0
Guidelines for posting comments:
- You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
- In-depth discussions should take place on the forum.
For more information see the full version of the ticket guidelines here.
I suppose, there are some erros in the fastcall-implementation for the XMM-Registers either in DllCallAddress or DllCallback.