Modify

Opened 8 years ago

Closed 8 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 8 years ago by anonymous

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

comment:2 Changed 8 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 8 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 8 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 8 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.

Add Comment

Modify Ticket

Action
as closed The owner will remain trancexx.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.