Opened 14 years ago
Closed 14 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 )
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 by , 14 years ago
comment:2 by , 14 years ago
| Description: | modified (diff) |
|---|---|
| Keywords: | dllcallbackregister added; dllcalladdress removed |
| Summary: | DllCallAddress Corrupts float Type under x64 → 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 by , 14 years ago
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 by , 14 years ago
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 by , 14 years ago
| Milestone: | → 3.3.9.0 |
|---|---|
| Owner: | set to |
| Resolution: | → Fixed |
| Status: | new → closed |
Fixed by revision [6588] in version: 3.3.9.0

I suppose, there are some erros in the fastcall-implementation for the XMM-Registers either in DllCallAddress or DllCallback.