I am having some serious issues with delphi rounding (when used from a c# project) and consistency of it's results when the value seems to fall within the .5 bracket i.e. is it rounding up or down???
I have created a delphi DLL that performs a number of operations. The crux of one of the operations is (as an example)
double := Round(double1 * double2);
where double1 = 1.9 and double2 = 225 (values obtained from file these are read from)
The result on my calculator says it should be 427.5. The result in the delphi DLL says 427. Rounding down, all good as per delphi documentation for Round()
The values of these calculations are stored against Delphi (classes I believe) which represent forms. In the case above like so
property SRDairy : Double read FSRDairy write FSRDairy;
This property belongs to a bunch of classes and is serialized to the buffer in the Delphi DLL like so (AOvrFarm is the parent that contains all the items to be serialized included my SRDairy one)
procedure GetResultString(AOvrFarm: TdataV6; outputStringBuffer: PChar; var
bufLen: Integer);
var
MyStrings : TStringList;
resultString : string;
begin
MyStrings := TStringList.Create;
try
AOvrFarm.SavetoStrings(MyStrings);
resultString := MyStrings.Text;
if outputStringBuffer = nil then
begin
bufLen := Length(resultString) + 1;
end
else
begin
StrLCopy(outputStringBuffer, PChar(resultString), bufLen - 1);
end;
finally
MyStrings.Free;
end;
end;
There are a-lot of other properties, forms (classes) etc that are done in this DLL. Upon the end, this file is serialised to a string and that string is returned to the caller (c#) app and the refoutputStringBuffer is filled using something like (in delphi):
StrLCopy(outputStringBuffer, PChar(resultString), bufLen - 1);
My issue is when I'm calling this DLL from a c# application. The result I'm getting is not 427, it's 428. Rounded up!!!!
The Delphi signature:
function ConvertString(fileContents: PChar; fileExt: PChar; var outputStringBuffer: PChar; var outputStringBufferSize: Integer; var errorMsgBuffer: PChar; var errorMsgBufferSize: Integer): WordBool; stdcall; export;
I use the DLL from my c# like so:
[DllImport("OvrFileImport.dll",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
public static extern bool
ConvertString(
string fileContents,
string fileExt,
ref string refputStringBuffer,
ref int outputStringBufferSize,
ref string errorMsgBuffer,
ref int errorMsgBufferSize);
The convert string is called once to get the buffer size and then again to fill the buffer. It's on the second call that I notice the difference. When using the same DLL from a Test Delphi project I get 427 (rather than the c# 428).
I've tried building my c# against Any CPU and just x86 incase it was some sort of cpu 64bit issue as my PC is a 64bit machine.
Has anyone ever come across this kind of thing, and if so did they have any way around it?
EDIT - ANSWER
As mentioned by David Heffernan the control word used when calling the DLL from c# was different to that used when calling from another Delphi application. The control word used when calling from c# was in fact $639.
Unfortunately, setting the control word to $1372 caused issues in my c# app while debugging namely it caused the local's watch window to show "unable to evaluate due to stack overflow state" exceptions for all variables. I found an article - strange floating point results which talks about this and hence changed it to be $133F instead (which resolved both the floating point differences and the c# debugging issues).
Code being:
begin
cw := Get8087CW;
Set8087CW($133F);
....
finally
Set8087CW(cw);
out
parameters above?) C# will "truncate" as well when casting to an integer type... – user166390