Compiler error "E2003 Undeclared identifier" - delphi

In this code:
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms, Dialogs, IdBaseComponent, IdComponent, IdTCPConnection,
IdTCPClient, IdIOHandler, IdGlobal, StdCtrls;
function WaitForCommand(args: Pointer): Cardinal; stdcall;
begin
while client.Connected do
if not HandleResponse(client.IOHandler) then
break;
Result := 0;
end;
I have this error:
[DCC Error] Unit1.pas(159): E2003 Undeclared identifier: 'HandleResponse'

How to understand messages?
Let's read it in parts:
[DCC Error]
DCC is the Delphi Compiler, so it is about our code, not about linking or packaging.
Unit1.pas
The file in which the error occurred. Normally Delphi's editor automatically display this file to you.
(159)
The line in which an error occurred. Normaly Delphi's editor automatically puts your text cursor into this line.
E2003
That's is the code of the error in case any further text is unavailable. It is like HTTP's status 404 is a code (with the actual text "Not Found" for it) or like a traffic's light red is a code (without any further text telling you to stop).
Undeclared identifier:
At this point the compiler does not know how to interpret what is now named. And and even cannot tell you if it is a missing function, a missing type, or else - hence the overall term "identifer".
'HandleResponse'
Normally Delphi's editor automatically puts your text cursor in the line of issue at the start of the text that cannot be understood.
What could you do?
It is undeclared. Declare it. However, only you can know what you want. You could
declare a type:
type
HandleResponse= Boolean;
define a function:
function HandleResponse(h: TIdIOHandler): Boolean;
begin
result:= FALSE;
end;
import a function from a DLL:
function HandleResponse(p: Pointer): LongBool; stdcall; external 'any.dll';
add the unit that might already have it:
uses
WhatIsMissingSoFar;
...or do other things I yet have to remember. But I'm sure you understand that in these 3 examples the identifier HandleResponse is now declared. I don't have to tell you that declarations must be done before using it, right?

Related

Previous declaration of CalculateInventoryColumnWidths not marked with the 'overload' directive

I'm getting the above error in the following unit (Delphi Alexandria) along with an "Unsatisfied forward or external declaration of 'CalculateInventoryColumnWidths'" error:
unit InventoryListing;
interface
uses
Classes, FireDac.Comp.Client, FMX.StdCtrls, FMX.frxClass,
AppGlobals;
procedure CalculateInventoryColumnWidths(var ColWidths: TColWidthsArray;
var TopTitles, MiddleTitles, BottomTitles: TStringList);
implementation
uses
SysUtils, StrUtils, System.Variants, System.UITypes,
Globals, Data;
type
TColWidthsArray = array of single;
var
fInventorySQL: string;
procedure CalculateInventoryColumnWidths(var ColWidths: TColWidthsArray;
var TopTitles, MiddleTitles, BottomTitles: TStringList);
begin
{implementation code}
end;
End.
I've searched the whole project for this procedure name and only found one instance that is the actual call to this procedure. I've tried removing the original unit from the project (that had all the details of the procedure) and created a brand new unit (above) to test with and still got the above errors.
I'm sure I'm doing something wrong here, but can't for the life of me figure it out. Can someone please help me see where I've gone wrong?
The interface declaration references TColWidthsArray, which is probably declared in AppGlobals, but the implementation references the local declaration of TColWidthsArray given a few lines above. So both reference different types and thus don't match.

Is it good practice to exploit a compiler bug?

Recently I found some odd-looking (to me) Delphi code and I have isolated it to a separate small project. Here is what I discovered. Unit1 compiles with no errors. Unit2 (which I provide for comparison) does not. The difference is in the way that Classes is used.
unit Unit1;
interface
uses Classes; // difference here
type TThread = class(Classes.TThread)
public
property Terminated;
end;
implementation
end.
Unit2 does not compile. Various errors are produced.
unit Unit2;
interface
uses System.Classes; // difference here
type TThread = class(Classes.TThread)
public
property Terminated;
end;
implementation
end.
[dcc32 Error] Unit1.pas(7): E2003 Undeclared identifier: 'Classes'
[dcc32 Error] Unit1.pas(7): E2029 ',' or ':' expected but ')' found
[dcc32 Error] Unit1.pas(9): E2147 Property 'Terminated' does not exist in base class
So my concern is that this project is exploiting a compiler bug to achieve it's goals. The compiler bug might be fixed in a later release, and then the code won't work anymore.
There is no compiler bug that makes Unit1 compile. It compiles because in the project setting the entry for Unit Scope Names contains at least the item System, which is used to resolve the reference to Classes in the full name System.Classes. As the uses contains Classes, the reference to Classes.TThread also succeeds.
In Unit2 the uses contains System.Classes. Therefore the reference Classes.TThread cannot be resolved anymore. Change it to System.Classes.TThread and it works.
If you uses System.Classes you must also use System.Classes when referring to the classes unit in the code as shown below.
unit Unit2;
interface
uses System.Classes; // difference here
type TThread = class(System.Classes.TThread)
public
property Terminated;
end;
implementation
end.

"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());

Delphi giving syntax errors: . expected but ; found error

I am toying around in Delphi XE6, and add this procedure on a button:
procedure TTabbedForm.btnLoadingClick(Sender: TObject);
var
dlg: Unit2;
begin
dlg := Form2.Create(nil);
Form2.ShowModal();
end;
Delphi gives me the following error while compiling:
[DCC Error] TabbedTemplate.pas(53): E2029 '.' expected but ';' found
[DCC Error] TabbedTemplate.pas(55): E2029 ';' expected but 'BEGIN' found
[DCC Fatal Error] Speelpleintjes.dpr(7): F2063 Could not compile used unit 'TabbedTemplate.pas'
Line 53 being: dlg: Unit2;
Honestly i'm quite puzzled, the syntax seems correct, the procedure is auto generated from the events tab.
Any suggestions?
If Unit2 is another unit in your project (judging by it's name it probably is), it can't be used as a type directly. Units only declare things. That's why the compiler is expecting a . since you can prefix an identifier with the unit's name to direct to a declaration in that specific unit.
To correct this, write dlg: TForm2;
Also it's common practice to call constructors from the class declaration, not a variable so change it to:
dlg := TForm2.Create(nil);
Or use the Form2 variable, which typically will hold an instance of TForm2 already. By default extra forms added to a Delphi project are created hidden, ready for Show or ShowModal.

Compiler error when calling Windows API with correct parameters

I am trying to run this elementary function but it will not work :
function GetWindowsUserName: String;
const
MAX_LENGTH = 256;
var
UserNameLength: DWord;
begin
UserNameLength := MAX_LENGTH - 1;
SetLength(Result, MAX_LENGTH);
if GetUserName(PChar(Result), UserNameLength) then
SetLength(Result, UserNameLength - 1)
else
Result := '';
end;
On formCreate I have :
AdvOfficeStatusBar1.Panels[0].Text := GetWindowsUserName;
I get :
[dcc32 Error] Unit1.pas(115): E2034 Too many actual parameters
[dcc32 Error] Unit1.pas(115): E2012 Type of expression must be BOOLEAN
What am I missing here ?
Edit : I am still getting the error :
When you report a compiler error, you must indicate which line of the code the error applies to. In this case, the only line of code that can report that error is the call to GetUserName.
The only way in which the call to GetUserName could fail in that way would be for there to be an unexpected GetUserName in scope. Your code expects to find the GetUserName defined in the Windows. Clearly a different version is in scope.
You can fully specify the symbol to make the compiler use the right one:
Windows.GetUserName
or if you are using namespaces:
Winapi.Windows.GetUserName
Try this.
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
- - - - - -
{ Get current username. }
function TForm1.GetCurrentUser(): String;
var
lpUserName: array[0..256] of Char;
nSize: DWord;
begin
// Get current loginname
nSize := SizeOf(lpUserName);
GetUserName(#lpUserName, nSize);
Result := lpUserName;
end;
Its this function you must use, maybe Uses imports give you something else but similar name. But this is oldskool method.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724432%28v=vs.85%29.aspx
New method is SSPI interface. (scrap this sspi is actually authenticating user+pwd values against WinAD. GetuserName is fine just reading active windows identity)
http://www.michael-puff.de/Programmierung/Delphi/Units/SSPIValidatePassword.pas

Resources