i have a problem compiling my Delphi code.
I have 3 classes, XmlFileManager (concrete), XmlNodeManager (abstract), XmlEnpManager (child of XmlNodeManager and concrete).
Below, a little of definition class code:
XmlFileManager
unit XmlFileManager;
interface
uses
xmldom, XMLIntf, msxmldom, XMLDoc, SysUtils, DateUtils, Classes, Dialogs,
XmlNodeManager, XmlEnpManager;
type
TXmlFileManager = class
[...]
end;
[...]
end.
XmlNodeManager
unit XmlNodeManager;
interface
uses
xmldom, XMLIntf, msxmldom, XMLDoc, SysUtils, DateUtils, Classes, Dialogs,
XmlFileManager;
type
TXmlNodeManager = class
[...]
end;
[...]
end.
XmlEnpManager
unit XmlEnpManager;
interface
uses
xmldom, XMLIntf, msxmldom, XMLDoc, SysUtils, DateUtils, Classes, Dialogs,
XmlFileManager, XmlNodeManager;
type
TXmlEnpManager = class (TXmlNodeManager)
[...]
end;
[...]
end.
In the XmlNodeManager and XmlEnpManager, not recognize TXmlFileManager class. An whe i compile, the compilation fails with message:
[dcc32 Fatal Error] SiGAS.dpr(23): F1026 File not found:
'XmlManager.dcu'
In the past, the XmlFileManager was called XmlManager.
Any ideas ?.
My .dpr:
uses
Forms,
Main in 'forms\Main.pas' {Principal},
Globals in 'units\Globals.pas',
CrearProyectoForm in 'forms\CrearProyectoForm.pas' {NuevoProyecto},
Validadores in 'units\Validadores.pas',
IdiomaClass in 'units\IdiomaClass.pas',
IdiomaCastellanoClass in 'units\IdiomaCastellanoClass.pas',
ExcelFileManagerClass in 'units\ExcelFileManagerClass.pas',
SeleccionarIdioma in 'forms\SeleccionarIdioma.pas' {SelectLang},
EnpView in 'forms\EnpView.pas' {ENP},
EnpViewGeneric in 'forms\EnpViewGeneric.pas' {EnpGeneric},
Vcl.Themes,
Vcl.Styles,
EnpViewAdd in 'forms\EnpViewAdd.pas' {EnpAdd},
EnpViewAddAfter in 'forms\EnpViewAddAfter.pas' {EnpAddAfter},
EnpViewEdit in 'forms\EnpViewEdit.pas' {EnpEdit},
EnpInicial in 'forms\EnpInicial.pas' {ENPViewInicial},
XmlFileManager in 'units\XmlFileManager.pas',
XmlNodeManager in 'units\XmlNodeManager.pas',
XmlEnpManager in 'units\XmlEnpManager.pas';
Your main source file, SiGAS.dpr, still has it listed as XmlManager, so...
Open your *.dpr file (it is just Delphi code) and fix the unit name in the uses clause, then rebuild.
Related
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?
I am new to delphi 7, I installed TntControls into delphi7, and replace TForm to TTntForm, code like below:
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, TntStdCtrls;
type
TForm1 = class(TTntForm)
private
{ Private declarations }
public
{ Public declarations }
end;
But when I compile, the error throw:
Undeclared identifier: 'TTntForm'
As people told you in comments, you have to add TntForms into the uses section. The source code is publicly available on GitHub.
In case you still have the same error, be sure that the path to the TntForms.pas is added to Tools > Environment Options > Library > Library Path or at least under Project > Options > Directories/Conditionals.
I manage a huge project in Delphi 2007. The target is to upgrade it to Delphi 10.1 Berlin this year. So in the meantime the source is compiled in both versions.
If there is a problem with the new Delphi we want the old version as backup.
My problem in unit dmActions.pas that is a unit inherited from TDataModule.
uses
// VCL
ActnList,
ActnMan,
Classes,
Controls,
Forms,
Graphics,
ImgList,
Menus,
SysUtils,
XPStyleActnCtrls,
Variants,
{$IFDEF BOLD_DELPHI16_OR_LATER}
System.ImageList,
System.Actions,
{$ENDIF}
BusinessClasses;
Delphi IDE don't understand my IFDEF so it automatically insert missing units to this
uses
// VCL
ActnList,
ActnMan,
Classes,
Controls,
Forms,
Graphics,
ImgList,
Menus,
SysUtils,
XPStyleActnCtrls,
Variants,
{$IFDEF BOLD_DELPHI16_OR_LATER}
System.ImageList,
System.Actions,
{$ENDIF}
BusinessClasses, System.ImageList, System.Actions;
But this don't compile in Berlin with this message
[dcc32 Error] dmActions.pas(36): E2004 Identifier redeclared: 'System.ImageList'
[dcc32 Error] dmActions.pas(36): E2004 Identifier redeclared: 'System.Actions'
And of course "System.ImageList, System.Actions" don't compile in D2007.
So what is my best action to solve this ?
You can make use of the Unit Aliases feature of Delphi here - at least as your Delphi 2007 supports dotted unit names in the first place. This allows to use the new unit names like System.SysUtils from Delphi 10.1 Berlin and still compile that project with Delphi 2007.
For this you have to add mappings to the Unit Aliases of the Delphi 2007 project like this:
System.SysUtils=SysUtils
System.Classes=Classes
For units that don't exist in Delphi 2007, like the ones you mention in your post, simply map to an existing unit:
System.Actions=ActnList
System.ImageList=ImgList
As a benefit you end up with uses clauses free of IFDEFs.
As https://stackoverflow.com/users/2916756/nolaspeaker said it works by test compiler version directly. I used an inc-file and that don't work well in this case
But in my case I check Berlin so:
{$IFDEF VER310}
System.ImageList,
System.Actions,
{$ENDIF}
There are code below and worked well before
unit Unit1;
{$DEFINE _Full}
// {$DEFINE _Trial}
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms;
{$ifdef _Trial}
_programname='abc';
{$endif}
{$ifdef _Full}
_programname='abc';
{$endif}
but today I run Delphi and try to compile, it reported
Identifier redeclared: '_programname'
it looks like
{$DEFINE _Full}
does not work
your comment welcome
Both conditionals are defined. That can be inferred from the compiler error.
Either single line // comments do not comment out defines. Or you are defining _Trial at the project level. To the very best of my knowledge, a single line // comment will comment out a directive. So I presume that _Trial is defined at the project level.
The idiomatic way to comment out defines is like this:
{.$DEFINE _Trial}
For an either or condition it might be simpler with a single conditional:
{$IFDEF _Trial}
.... stuff for trial version
{$ELSE}
.... stuff for full version
{$END}
All that said, perhaps your actual problem is different because the code you show does not match the error message you reported. I'd expect an error saying that a keyword was expected, but identifier _programname found. The code in the question appears to omit the const keyword before the declaration of _programname.
I am submitting this under the assumption that _programname is supposed to be a constant, as that is most consistent with t
he code you are showing. Your constant declarations need to be declared in a CONST section block. Try this:
unit Unit1;
{$DEFINE _Full}
// {$DEFINE _Trial}
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms;
CONST //<< Changed Code
{$ifdef _Trial}
_programname='abc';
{$endif}
{$ifdef _Full}
_programname='abc';
{$endif}
i need develop the next diagram class:
I wrote code, but, have problems of circular unit reference.
The XmlFileManager Class contains:
unit XmlFileManager;
interface
uses
xmldom, XMLIntf, msxmldom, XMLDoc, SysUtils, DateUtils, Classes, Dialogs,
XmlEnpManager;
type
TXmlFileManager = class
private
[...]
xmEnp: TXmlEnpManager;
xmEnpInicial: TXmlEnpManager;
xmEnpFinal: TXmlEnpManager;
[...]
end.
The abstract class, XmlNodeManager:
unit XmlNodeManager;
interface
uses
xmldom, XMLIntf, msxmldom, XMLDoc, SysUtils, DateUtils, Classes, Dialogs,
XmlFileManager;
type
TXmlNodeManager = class
protected
{ sgy alias para strategy }
sgyIterator: Integer;
sgyContext: TXmlFileManager;
sgyAttributes: TStringList;
sgyNode: IXMLNode;
[...]
end.
And the XmlEnpManager concrete class:
unit XmlEnpManager;
interface
uses
xmldom, XMLIntf, msxmldom, XMLDoc, SysUtils, DateUtils, Classes, Dialogs,
XmlNodeManager;
type
TXmlEnpManager = class (TXmlNodeManager)
public
constructor Create(aContext: TXmlFileManager); overload; override;
constructor CreateInicial(aContext: TXmlFileManager); reintroduce; overload;
constructor CreateFinal(aContext: TXmlFileManager); reintroduce; overload;
[...]
end.
The builds fails with error:
[dcc32 Fatal Error] XmlNodeManager.pas(7): F2047 Circular unit
reference to 'XmlFileManager'
Any ideas how to solve this problem ?.
Put TXmlFileManager and TXmlNodeManager in both the same unit and the same type section, then make sure that type section starts with this class forward: TXmlNodeManager = class;
See the official documentation: Forward Declarations and Mutually Dependent Classes.
unit XmlFileManagerAndXmlNodeManager;
interface
uses
xmldom, XMLIntf, msxmldom, XMLDoc, SysUtils, DateUtils, Classes, Dialogs,
[...]
type
TXmlNodeManager = class;
TXmlFileManager = class
private
[...]
xmEnp: TXmlEnpManager;
xmEnpInicial: TXmlEnpManager;
xmEnpFinal: TXmlEnpManager;
[...]
TXmlNodeManager = class
protected
sgyIterator: Integer;
sgyContext: TXmlFileManager;
sgyAttributes: TStringList;
sgyNode: IXMLNode;
[...]
end.
If possible, easiest way is to have all classes in same unit.
Although putting all classes in the same unit is a perfect solution, you might consider breaking the mutual reference by interfacing at least one of the classes, defining that interface in a separate unit and letting the other unit refer to the unit with the interface in its interface section. Then you can move the first unit reference from the interface to the implementation.The creation of an instance will then be done in the implementation section, where a mutual reference is allowed, but thus breaking the mutual reference in the interface section, which is not allowed, as you already noticed. This allows you to keep both classes in a separate unit, should that be required.
Hope this makes sense.
If the reference between the units is in the implementation section instead of the interface section then this will work.
You could create a base class in another unit with no out going reference and reference it from the interface and cast into the actual class on demand by adding the specific unit reference to the implementation section.
In XMLNodeManager, Make:
sgyContext: TObject;
Then you don't need to use the unit XmlFileManager in interface. Use it in the Implementation section's Uses clause. When using sgyContext in the implementation code, cast it to TXmlFileManager(sgyContext).