Modify

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 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 by anonymous, 14 years ago

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

comment:2 by Valik, 14 years ago

Description: modified (diff)
Keywords: dllcallbackregister added; dllcalladdress removed
Summary: DllCallAddress Corrupts float Type under x64DllCallbackRegister() 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 anonymous, 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 Valik, 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 trancexx, 14 years ago

Milestone: 3.3.9.0
Owner: set to trancexx
Resolution: Fixed
Status: newclosed

Fixed by revision [6588] in version: 3.3.9.0

Modify Ticket

Action
as closed The owner will remain trancexx.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.