Confused by UInt64 - delphi

The code snippet below demonstrates a problem I am having with with text IO and UInt64 type variables in Delphi XE2 recently re-installed from a recent ISO image file - the compile fails with an error message relating to a missing Text.ReadUInt64 function or procedure. If I replace the failing line with
ReadLn(F,A);
then the program compiles, correctly writes
-1
18446744073709551615
to the text file, and then (as expected) fails on the second read with an EInOutError: "Invalid Numeric Input". Do I have a corrupt install or has someone failed to write a ReadUInt64 function? The only reference to ReadUInt64 that I can find in help is the following definition:
function ReadUInt64: UInt64; virtual;
in System.Classes.TBinaryReader.ReadUInt64. I'm not sure if this is the 'same' function or, if so, why it is virtual...
I am also a little confused by Help's reference to UInt64. It defines it as:
type UInt64 = Int64;
If this is correct, how does the compiler know to treat an UInt64 differently to an Int64 variable?
procedure TForm1.Button1Click(Sender: TObject);
var
F : TextFile;
A : Int64;
B : Uint64;
begin
{
Compiler warns on following line with message:
[DCC Warning] Unit1.pas(32): W1012 Constant expression violates subrange bounds
}
A := $FFFFFFFFFFFFFFFF;
B := $FFFFFFFFFFFFFFFF;
AssignFile(F,'test.txt');
ReWrite(F);
Writeln(F,A);
Writeln(F,B);
CloseFile(F);
AssignFile(F,'test.txt');
ReSet(F);
ReadLn(F,A);
{
Fails to compile on following line with message:
[DCC Fatal Error] Unit1.pas(42): E2158 System unit out of date or corrupted: missing 'Text.ReadUInt64'
}
ReadLn(F,B);
CloseFile(F);
end;

See QC102876. This is a known bug, reported as Text.ReadUInt64 missing, with the description:
The compiler generates a call to Text.ReadUInt64, when an UInt64 should be read from a stream. The linker, however, complains that Text.ReadUInt64 is missing.
This issue (bug) is resolved in XE3 (build #17.0.4625.53395), according to QC.

Related

"reference to function" as result of a function

i have a function that returns a function TFunc<Integer> which is reference to function:Integer.
and i have a procedure which takes a function TFunc<Integer> as argument, calls it and prints its result.
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
function GetFunction:TFunc<Integer>;
begin
result := function:Integer begin result := 42 end;
end;
procedure FunctionCall(AFunc:TFunc<Integer>);
var i:Integer;
begin
i := AFunc;
WriteLn(Format('Function Result = %d',[i]));
end;
begin
// FunctionCall(GetFunction); // error
FunctionCall(GetFunction()); // works as excpected
end.
this call (FunctionCall(GetFunction);) results in an error. and the call with () works as excpected.
my question is:
when in delphi do i need brakets to call a function and when not (i thought that i never need them)
or
shouldn't i need them and is it a bug?
i work with delphi xe5 on windows 7 dcc32.
If what you report is correct (and see below for more on that), then you would have found a bug, I believe.
This code:
FunctionCall(GetFunction);
should not compile. Indeed it does not compile when I try to compile it in XE3, XE4, XE5, XE6 and XE7. It does not compile because, in this particular context, the compiler interprets GetFunction as being of type
function: TFunc<Integer>
All above mentioned compilers object with this error message:
[dcc32 Error] E2010 Incompatible types: 'System.SysUtils.TFunc' and 'Procedure'
So, if you have somehow (perhaps with some compiler options), managed to make that code compile then I can only believe that is due to a bug.
You should deal with this by applying the parentheses so that the compiler can understand that you wish to call GetFunction, not refer to it.
FunctionCall(GetFunction());

How to adjust the level of compression with TZCompressionStream?

When I create a TZCompressionStream object with:
var
cs: TZCompressionStream;
dest: TStream;
level: TZCompressionLevel;
...
cs := TZCompressionStream.Create(level, dest);
I get this compiler error:
E2250 There is no overloaded version of 'Create' that can be called with these arguments
But my code is according to the constructor declaration:
Create(compressionLevel: TZCompressionLevel; dest: TStream); overload;
When I used XE, everything was OK. But now with XE5 there is this error. Why?
Update:
Working code: cs := TZCompressionStream.Create(dest);
Faliing code: cs := TZCompressionStream.Create(clMax, dest);
I also tried to change the order of the arguments, which was unsuccessful.
I'm assuming that your code is as stated in your edit:
cs:=TZCompressionStream.Create(clMax, dest);
The obvious explanation is that clMax is not what you think it is. There is probably another unit that defines clMax and that unit appears after ZLib in your list of uses. Solve the problem by either:
fully qualifying the enumerated value: ZLib.clMax, or
change the order of the uses so that ZLib appears after the unit which defines the other clMax.

delphi E2003 undeclared identifier 'self'

I need a bit of help; I'm helping a friend port a Delphi app built years back to newer versions of Windows, as it currently only runs on Windows 95.
The code utilises 3rd party libraries from Woll2Woll for DB operations.
One of these libraries generates the error E2003 Undeclared identifier: 'self'.
I've been through a number of sites via Google and with my limited knowledge of Delphi (stemming from my Pascal training about 12 years ago and extrapolating my slightly rusted PHP, BASH, ColdFusion and ASP coding skills), I've run into a brick wall - I'm strapped for time and can't make sense of the info I'm coming across on the web.
The problematic code segment is from the wwwQuery.pas file and looks like this:
{$ifdef wwDelphi3Up}
procedure TwwQuery.OpenCursor(InfoQuery: Boolean);
{$else}
procedure TwwQuery.OpenCursor;
{$endif}
begin
{$ifdef wwDelphi3Up}
inherited OpenCursor(InfoQuery);
{$else}
inherited OpenCursor;
{$endif}
//Modded by Arie
//wwSaveAnswerTable(self, Handle, FAnswerTable);
wwSaveAnswerTable(self, Handle, 'FAnswerTable');
end;
The precise error messages are:
[DCC Error] wwQuery.pas(243): E2003 Undeclared identifier: 'self'
[DCC Error] wwQuery.pas(244): E2029 '.' expected but ';' found
[DCC Fatal Error] wwcommon.pas(285): F2063 Could not compile used unit 'wwQuery.pas'
Line 243 is the 2nd last line, just above the end;
The wwSaveAnswerTable function looks like this:
Function wwSaveAnswerTable(ADataSet: TDBDataSet; AHandle: HDbiCur; tableName: string): boolean;
What must I change the Self parameter to, to stop the compile error?
Thanks a stack.
The problem is related to compiler define wwDelphi3Up or any related up in code.
As you see next error message: [DCC Error] wwQuery.pas(244): E2029 '.' expected but ';' found
Compiler expects end of program, and line wwSaveAnswerTable(self, Handle, 'FAnswerTable'); are not compiled inside OpenCursor method. That's why Self is not defined.
You don't need to change parameter, because for sure will affect functionality.
Try to compile it without defines, if you are not use an ancient version of Delphi:
procedure TwwQuery.OpenCursor(InfoQuery: Boolean);
begin
inherited OpenCursor(InfoQuery);
wwSaveAnswerTable(self, Handle, 'FAnswerTable'); // Here prob FAnswerTable without quotes
end;

Delphi - E2010 Incompatible types: 'Integer' and 'Char' - Any ideas

I've been tasked with porting a legacy Delphi application over to C# .Net. The original delphi developer left several months before I was hired. I'm receiving the:
E2010 Incompatible types: 'Integer' and 'Char' error
for the below method. I'm trying to compile the application within the Delphi 2007 IDE, I've been told that original application is either Delphi 4 or 5 if that helps any. I understand what the error is telling me but I don't understand why\how it is applied to the code snippet below. Any help\direction would be greatly appreciated.
Thanks in advance - not sure if I've over done it on the code.
Upper definition:
Upper: array[1..256] of Char =
(#$00,#$01,#$02,#$03,#$04,#$05,#$06,#$07,#$08,#$09,#$0A,#$0B,#$0C,#$0D,#$0E,#$0F,
#$10,#$11,#$12,#$13,#$14,#$15,#$16,#$17,#$18,#$19,#$1A,#$1B,#$1C,#$1D,#$1E,#$1F,
#$20,#$21,#$22,#$23,#$24,#$25,#$26,#$27,#$28,#$29,#$2A,#$2B,#$2C,#$2D,#$2E,#$2F,
#$30,#$31,#$32,#$33,#$34,#$35,#$36,#$37,#$38,#$39,#$3A,#$3B,#$3C,#$3D,#$3E,#$3F,
#$40,#$41,#$42,#$43,#$44,#$45,#$46,#$47,#$48,#$49,#$4A,#$4B,#$4C,#$4D,#$4E,#$4F,
#$50,#$51,#$52,#$53,#$54,#$55,#$56,#$57,#$58,#$59,#$5A,#$5B,#$5C,#$5D,#$5E,#$5F,
#$60,#$41,#$42,#$43,#$44,#$45,#$46,#$47,#$48,#$49,#$4A,#$4B,#$4C,#$4D,#$4E,#$4F,
#$50,#$51,#$52,#$53,#$54,#$55,#$56,#$57,#$58,#$59,#$5A,#$7B,#$7C,#$7D,#$7E,#$7F,
#$80,#$81,#$82,#$83,#$84,#$85,#$86,#$87,#$88,#$89,#$8A,#$8B,#$8C,#$8D,#$8E,#$8F,
#$90,#$91,#$92,#$93,#$94,#$95,#$96,#$97,#$98,#$99,#$9A,#$9B,#$9C,#$9D,#$9E,#$9F,
#$A0,#$A1,#$A2,#$A3,#$A4,#$A5,#$A6,#$A7,#$A8,#$A9,#$AA,#$AB,#$AC,#$AD,#$AE,#$AF,
#$B0,#$B1,#$B2,#$B3,#$B4,#$B5,#$B6,#$B7,#$B8,#$B9,#$BA,#$BB,#$BC,#$BD,#$BE,#$BF,
#$C0,#$C1,#$C2,#$C3,#$C4,#$C5,#$C6,#$C7,#$C8,#$C9,#$CA,#$CB,#$CC,#$CD,#$CE,#$CF,
#$D0,#$D1,#$D2,#$D3,#$D4,#$D5,#$D6,#$D7,#$D8,#$D9,#$DA,#$DB,#$DC,#$DD,#$DE,#$DF,
#$E0,#$E1,#$E2,#$E3,#$E4,#$E5,#$E6,#$E7,#$E8,#$E9,#$EA,#$EB,#$EC,#$ED,#$EE,#$EF,
#$F0,#$F1,#$F2,#$F3,#$F4,#$F5,#$F6,#$F7,#$F8,#$F9,#$FA,#$FB,#$FC,#$FD,#$FE,#$FF);
function StrIComp_JOH_PAS_1(const Str1, Str2: PChar): Integer;
var
Ch1, Ch2 : Char;
Offset : Integer;
PStr : PChar;
begin;
PStr := Str1;
Offset := Str2 - PStr;
repeat
Ch1 := Upper[PStr^];
Ch2 := Upper[PStr[Offset]];
if (Ch1 = #0) or (Ch1 <> Ch2) then
Break;
Inc(PStr);
until False;
Result := Integer(Ch1) - Integer(Ch2);
end;
The code that you have has had an incorrect modification made to the Upper constant. It should be:
Upper: array[Char] of Char = ....
Of course, even better would be to simply throw this routine away and use the version of StrIComp that is shipped with Delphi in the SysUtils unit. There seems little point in grappling with this when simply deleting the code will result in a program that is correct.
Since you are porting this to C# you can simply use String.Compare and pass true to the ignoreCase parameter.
Thanks to #Ulrich for recognising that this code originates from the FastCode project.
Is there const Upper definition in your pascal module?
If not, get it from here

Returning a string from a BPL function

have a function, simplified below, that is exported from a BPL
function DoA(amount: currency; var Info: string): Currency; stdcall;
begin
result := amount * 19;
Info:= 'Some Text about the result';
end;
its loaded from the main program with LoadPackage, and GetProcAddress which works fine for the other functions.
but this one brings up many errors when its called;
BPL Is used with (simplified)
bplhandle: HModule;
BPLDoA: function (amount: currency; var Info: string): Currency; stdcall;
intoStr : string;
.
begin
bplhandle:=LoadPackage('test.bpl');
if bplhandle <> 0 then
begin
#BPLDoA:=GetProcAddress(bplhandle,'DoA');
if assigned(BPLDoA) then
result := BPLDoA(123, intoStr);
end;
end;
the exception that seems to happen at the end of the Procedure,
but the corrected text is returned into intoStr (viewed with a break point)
would the error have anything to do with the Info param being a var and/or a string?
The Error message is
Project Project1.exe raised exception class EInvalidPointer with message 'Invalid pointer operation'
thanks
more info>
another function from the same bpl/unit works fine
function DoB(amount: currency): Currency; stdcall;
result := amount * 19;
end;
Mad Except>
exception class : EInvalidPointer
exception message : Invalid pointer operation.
main thread ($1b7c):
0040276f +013 Project1.exe System #FreeMem
00404650 +01c Project1.exe System #LStrClr
00483814 +15c Project1.exe Unit1 97 +11 TForm1.Button3Click
00462430 +064 Project1.exe Controls TControl.Click
0045a870 +01c Project1.exe StdCtrls TButton.Click
You haven't configured your EXE project to "build with run-time packages." Find that in the "packages" section of your project options. (Documentation)
The EInvalidPointer exception comes when a memory manager tries to free something that it didn't allocate. That suggests you have two different memory managers active. Your BPL is using the one from the RTL package, which appears on your package's "requires" list. Your EXE, on the other hand, is using the memory manager compiled into the EXE module.
Fix that by telling your EXE to use run-time packages, and then make sure the RTL package is on the list of required packages.
Does your import declaration exactly match the exported function's signature?
Must be like this:
DoAProc: function (amount: currency; var Info: string): Currency; stdcall;
Another option if you don't want to be required to ship additional BPLs (which you will now that your main exe is using runtime BPLs), is to include the ShareMem unit in your project. Check out the "Sharing Memory" topic in the Delphi help file.
ms-help://embarcadero.rs2010/rad/Sharing_Memory.html

Resources