Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Wie kann ich eine Procedure einer anderen Unit aufrufen?


Saarpoint - Di 13.07.04 21:06
Titel: Wie kann ich eine Procedure einer anderen Unit aufrufen?
Hallo!

irgend etwas mach' ich falsch, aber ich weiß nicht was...

In Unit1 habe ich eine Procedure die auch von Unit2 benötigt wird.
Unit1 hat den Namen "Chicago" und Unit2 den Namen "StartGame"
In Chigago habe ich in der USES die StartGame mit aufgeführt.

Benötigt wird die Procedure LoadPGZ aus Unit1 (Chicago). Doch der Debugger meldet
mir:

[Fataler Fehler] Chicago.pas(51): Verwendete Unit 'StartGame.pas' kann nicht compiliert werden

Ich habe folgendermaßen versucht jeweils die Procedure aus Unit2 aufzurufen.

Chicago.LoadPGZ;
TMainForm.LoadPGZ;

aber immer der obige Fehler...

Muss ich da noch in den Bereichen privat, public und implementation
noch was angeben? Kenn mich da noch nicht so aus. Für ein Beispiel hierfür oder
zur Hilfe meines Problems wäre ich echt dankbar!

Gruß, Andy


Moderiert von user profile iconMotzi: Topic aus Neue Einträge / Hinweise / etc. verschoben am Di 13.07.2004 um 21:14
Moderiert von user profile icontommie-lie: Topic aus Sonstiges verschoben am Fr 16.07.2004 um 21:21 ;-)


Segelflieger - Di 13.07.04 23:26

Wenn du eine Proc aus der Unit Chicago in der Unit StartGame verwenden willst, nützt es wenig, wenn du StartGame unter USES in Chicago aufführst.
Andersherum wird ein Schuh draus: Binde die Unit Chicago in der Unit StartGame ein!

Was noch eine weitere Fehlerquelle sein kann:

Binde deine Unit nicht ganz oben unter USES ein, wo auch die ganzen Delphi-Units (Graphics, SysUtils etc...) stehen.

Binde Sie hier ein:

Delphi-Quelltext
1:
2:
3:
4:
5:
implementation

uses Chicago;

{$R *.dfm}


Saarpoint - Mi 14.07.04 22:24

In der obersten USES von StartGame stand tatsächlich Chicago drin.
Hab Chicago jetzt in den implementation-Bereich von StartGame geschrieben.
Aber was soll ich sagen... es funtzt immer noch nicht...

Unit Chicago

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
 private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;
  WuerfelSort, ComPlay: boolean;
  Temp: String;
  f: text;
  Display, Ton, MerkeSpieler, FrageEnde: integer;

implementation

{$R *.DFM}

uses ChildWin, About, Unit1, StartGame;


Unit StartGame;

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.DFM}

uses Unit1, Chicago;

.....

AssignFile(f, Number + '.PGZ'); Erase(f);
       PGZ_Select.Items.Delete(PGZ_Select.ItemIndex);
       PGZ_Select.Text :=''; LoadPGZ;
....


Auch wenn ich Chicago.LoadPGZ eingebe, erhalte ich den Fehler:
[Fehler] StartGame.pas(143): Undefinierter Bezeichner: 'LoadPGZ'

Andy


SvenAbeln - Mi 14.07.04 23:27

hallo,

Leider kann man in deinem Code nicht sehen wo die Prozedure LoadPGZ denn definiert ist.

Also rate ich mal munter drauf los:

Du hast einfach eine Prozedure definiert,
dann hast du die definition von LoadPGZ nicht in dem Interface Teil von der Unit Chicago stehen.
Von aussen kannst du nur auf Funktionen/Prozeduren und Klassen zugreifen wenn sie auch im Interface der Unit stehen.

z.B. so

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
Unit Chicago;

Interface
  ...
procedure LoadPGZ;
  ...

Implementation
  ...
procedure LoadPGZ;
begin
  ...
end;



Du hast die Prozedure in einer Klasse definiert, z.B. in TMainForm
Dann muß die Klasse im Interface definiert sein und die Prozedure muß innerhalb dieser Klasse auch Public sein.
Auf so eine Funktion kannst du dann nur über ein Objekt zugreifen z.B. MainForm.LoadPGZ

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
interface

type TMainForm = class(TForm)
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    procedure LoadPGZ;
end;

implementation

procedure TMainForm.LoadPGZ;
begin
  ...
end;


Gruß


Segelflieger - Mi 14.07.04 23:49

Hallo!

Der Fehler liegt hier:

Delphi-Quelltext
1:
2:
3:
4:
5:
implementation  

uses Chicago {...}// <- hier muss das hin  
 
{$R *.dfm}


Die Uses-Klausel muss vor der Compilerdirektive {$R *.dfm} eingebunden werden.

PS: Ich empfehle dir, für den Quelltext, den du hier im Forum postest, Delphi-Tags anstatt Code-Tags zu verwenden.


SvenAbeln - Fr 16.07.04 16:31

Hallo,

Zitat:

Der Fehler liegt hier:
[..]

Die Uses-Klausel muss vor der Compilerdirektive {$R *.dfm} eingebunden werden.


Das stimmt nicht.

Die Position von {$R *.dfm} hat keinen Einfluß auf das Uses.

Über {$R Dateiname} wird festgelegt welche Ressourcen-Dateien vom Linker hinzugebunden werden, dies hat aber keinen Einfluß auf den Compiler.


Gruß,


Anonymous - Fr 16.07.04 21:08

SvenAbeln hat folgendes geschrieben:

...
Das stimmt nicht
...


mehr unbedingt, falls du schon etwas an deiner Hauptunit verändert hast und auch sonst in den meisten Fällen, ansonsten aber schon. :P (Aber genau gesagt ist es schon richtig dass es hinter implementation gehört :D )


Saarpoint - Fr 16.07.04 23:39

Hi!

Die beiden haben Recht: Ich hab die Compilerdirektive {$R *.dfm} hinter die USES gesetzt, aber das ändert gar nichts!

In StartGame hab ich USES Chicago eingetragen und in Chicago hab ich es jetzt mal so
probiert, was aber nur zu einem anderen Fehler geführt hat:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
 private
    { Private declarations }
  public
    { Public declarations }
    procedure LoadPGZ(Sender: TObject);
  end;


Rufe ich nun LoadPGZ mit Chicago.LoadPGZ auf, erhalte ich:
[Fehler] StartGame.pas(143): Undefinierter Bezeichner: 'LoadPGZ' (... schon wieder! :( )

Mit TMainForm.Chicago:
[Fehler] StartGame.pas(143): Nicht genügend wirkliche Parameter

Ich bin schon kurz davor, die komplette Procedure zu kopieren und in der StartGame
einzufügen nur, damit Ruhe ist! :x
Aber das vergrößert nur unnötig das Programm und Stilmäßig... na, ja... :roll:

Andy


SvenAbeln - Mo 19.07.04 12:26

Hallo,

du hast LoadPGZ jetzt also innerhalb einer Klasse Definiert, daher muß der Zugriff über ein
Objekt dieser Klasse erfolgen.

Ich vermute mal die Prozedur steckt jetzt im TMainForm.
Dann muß der Zugriff über

Delphi-Quelltext
1:
  MainForm.LoadPGZ();                    



Zu dem zweiten Fehler
Zitat:
[Fehler] StartGame.pas(143): Nicht genügend wirkliche Parameter


Deine Prozedur erwartet jetzt laut definition einen Parameter (Sender)
Zitat:
procedure LoadPGZ(Sender: TObject);

und den hast du bei dem Aufruf nicht mit angegeben.


Saarpoint - Mo 19.07.04 19:42

Danke für eure Mühe, aber ich gebs auf...

Auch mit MainForm.LoadPGZ(); erhalte ich "Nicht wirklich genügend Parameter" :motz:
Ich kopier die Procedure einfach in die andere Unit...

Oder, wenn sich jemand freiwillig erklärt, zippe ich mein Projekt (ca. 350 kb)
und maile es zum selbst testen zu. :lupe:

Andy


SvenAbeln - Di 20.07.04 15:16

Hallo,

aber warum denn aufgeben.

Wie ich oben schon einmal geschrieben habe kommt der Fehler "Nicht wirklich genügend Parameter", da du die Prozedure mit Parameter definiert hast, aber beim aufruf keinen Parameter angibst.

Wenn du den Parameter nicht brauchst, ändere einfach die Definition deiner Prozedure.

z.B. so

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
  private
    { Private declarations }
  public
    { Public declarations }
    procedure LoadPGZ();  // <--- Ohne Parameter
  end;
...


implementation

procedure TMainForm.LoadPGZ();
begin
...
end;



Ansonsten übergeb beim Aufruf den richtigen Parameter.
z.B.

Delphi-Quelltext
1:
  MainForm.LoadPGZ(einObjekt);                    


Saarpoint - Di 20.07.04 16:13

Hi!

Das war's! Daaaaaannke! :rofl:

Der Fehler lag daran, dass ich

Delphi-Quelltext
1:
  procedure LoadPGZ;                    

statt

Delphi-Quelltext
1:
  procedure TMainForm.LoadPGZ;                    


geschrieben habe. Ich dachte, da sich die Procedure eh in TMainForm befindet,
muss ich das auch nicht weiter angeben. Aber anscheinds muss man das machen,
wenn man die Procedure aus einer anderen Unit aufrufen will.
Der Aufruf selbst klappt jetzt auch von überall mit "LoadPGZ;"
Angaben wie "TMainForm." oder "Chicago." brauche ich nicht mehr.
Auch die leeren Klammen kann man weglassen :D

Vielen Dank für eure Hilfe! :flehan: :lol:

Gruß, Andy