von wo wird die Procedure aufgerufen?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut

von wo wird die Procedure aufgerufen?

Beitragvon TT73GP7 » 6. Jun 2019, 10:06 von wo wird die Procedure aufgerufen?

Hallo zusammen,

sorry ich weiß leider nicht wie ich das am besten beschreiben soll, deswegen der Komische Titel.

Ich habe eine Procedure in der "Unit A"

Code: Alles auswählen
 
procedure showText (cText: String);
begin
  bla bla
//Ort des Aufrufs
ShowMessage('hallo du wurdest von der Unit B aufgerufen')
end;
 
 


diese Rufe ich in der "Unit B" auf.
gut das klappt alles

aber ich will in der "Unit A" wissen von welche Unit die Procedure aufgerufen wird.
Hat jemand nee Idee wie ich das rausfinden kann?

ist etwas blöd zubeschreiben :(

VG der Troll
TT73GP7
 
Beiträge: 232
Registriert: 29. Mär 2016, 20:45

Beitragvon fliegermichl » 6. Jun 2019, 12:00 Re: von wo wird die Procedure aufgerufen?

Wenn Dein Programm mit Debuginformationen compiliert wurde, kannst Du GetStackTrace verwenden.
In dem Beispiel habe ich ein Formular mit einem Button und folgendem Code:
Code: Alles auswählen
 
implementation
uses LCLProc;
 
{$R *.lfm}
 
procedure a;
var s : string;
begin
  s := GetStackTrace(False);
  ShowMessage(s);
end;
 
procedure b;
begin
  a();
end;
 
{ TForm1 }
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  b();
end;
 


Das erzeugt dann folgende Ausgabe
stacktrace.PNG
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
fliegermichl
Lazarusforum e. V.
 
Beiträge: 365
Registriert: 9. Jun 2011, 09:42

Beitragvon Frank Ranis » 6. Jun 2019, 12:47 Re: von wo wird die Procedure aufgerufen?

Hi,

fliegermichl hat geschrieben:Wenn Dein Programm mit Debuginformationen compiliert wurde, kannst Du GetStackTrace verwenden.
In dem Beispiel habe ich ein Formular mit einem Button und folgendem Code:
Code: Alles auswählen
 
implementation
uses LCLProc;
 
{$R *.lfm}
 
procedure a;
var s : string;
begin
  s := GetStackTrace(False);
  ShowMessage(s);
end;
 
procedure b;
begin
  a();
end;
 
{ TForm1 }
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  b();
end;
 


Das erzeugt dann folgende Ausgabe
stacktrace.PNG


Leider funzt dieser Code bei mir nicht .
GetStackTrace ist in der Unit LCLProc nicht vorhanden .
Hat ein paar Minuten gebraucht , bis ich herausgefunden habe , das die Funktionen nach Unit LazTracer verschoben wurden.
Also anstelle von USES LCLProc , USES LazTracer verwenden .
Ich habe aktuell Lazarus 2.0.2 r60954 FPC 3.0.4 x86_64-win64-win32/win64 .

Das ist jetzt natürlich richtig doof , weil dann alter Quell-CODE nicht mit dem aktuellen LAZ kompatibel ist und man dann Suchen muß .
Wer macht denn so was und aus welchem Grund ?
Die WIKI passt dann auch hinten und vorne nicht mehr http://wiki.freepascal.org/Logging_exce ... it_LCLProc .

Gruß

Frank
www.flz-vortex.de
Frank Ranis
 
Beiträge: 150
Registriert: 24. Jan 2013, 22:22
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z) | 
CPU-Target: xxBit
Nach oben

Beitragvon fliegermichl » 6. Jun 2019, 12:54 Re: von wo wird die Procedure aufgerufen?

Ja das ist doof. Ich habe Lazarus 1.8.5 und da ist das noch in LCLProc
fliegermichl
Lazarusforum e. V.
 
Beiträge: 365
Registriert: 9. Jun 2011, 09:42

Beitragvon TT73GP7 » 6. Jun 2019, 14:05 Re: von wo wird die Procedure aufgerufen?

aber sehr cool

das läuft perfekt
und mal wieder merkte ich das ich mal die Version updaten muss :D

nun habe ich aber noch ein anderes Problem
wenn ich nun auf der Unit b die Funktion auf der Unit A aufrufe
, möchte ich gerne ein Feld aus der DataSource von der Unit A auslesen
sprich DataSource.Dataset.FieldbyName('ID').ASString;

wie komme ich denn da ran?

klar ich könnte das einfach in einer Variable übergeben
aber genau das will ich mir ja sparen.
TT73GP7
 
Beiträge: 232
Registriert: 29. Mär 2016, 20:45

Beitragvon fliegermichl » 6. Jun 2019, 14:54 Re: von wo wird die Procedure aufgerufen?

TT73GP7 hat geschrieben:wenn ich nun auf der Unit b die Funktion auf der Unit A aufrufe
, möchte ich gerne ein Feld aus der DataSource von der Unit A auslesen
sprich DataSource.Dataset.FieldbyName('ID').ASString;

wie komme ich denn da ran?


a.Datasource.Dataset.FieldbyName('ID').AsString;
fliegermichl
Lazarusforum e. V.
 
Beiträge: 365
Registriert: 9. Jun 2011, 09:42

Beitragvon Warf » 6. Jun 2019, 16:48 Re: von wo wird die Procedure aufgerufen?

fliegermichl hat geschrieben:Wenn Dein Programm mit Debuginformationen compiliert wurde, kannst Du GetStackTrace verwenden.


Das das programm immer mit debuginformationen geliefert werden muss halte ich persönlich für eine herzlich beschissene idee. Der debug code in LCL programmen macht größenunterschiede im MB bereich aus. Außerdem schränkt das optimierungen (Namentlich inlining) extrem ein. Einfach nein!

Es gibt zwar andere möglichkeiten, z.B. könntest du unter den funktionsaufruf ein goto label setzen (damit kann es auch nicht wegoptimiert werden) und dann checken ob die returnaddresse die addresse von dem label ist. Das willst du aber eigentlich nicht machen.

Was man normalerweise macht ist z.B. der Sender Parameter in LCL events. Wenn ein Button geklickt wird wird der Event handler aufgerufen. Damit der weiß welcher button geklick wird, wird ihm die sender variable von TObject übergeben über die er das aufrufende Objekt identifizieren kann.

Wenn du dein programm eh OOP strukturiert hast (was ich bei Object Pascal wohl mal hoffen darf), solltest du die funktion eh aus einem anderen Objet aufrufen.
Beispiel:
Code: Alles auswählen
// UnitA:
TKlasseA = class
public
  procedure Foo(Sender: TObject);
end;
...
implementation
  uses UnitB;
...
procedureTKlasseA.Foo(Sender: TObject);
begin
  if (Sender is TKlasseB) then
    // Mach was mit (Sender as TKlasseB)
end;
 
// Unit B
uses UnitA;
...
TKlasseB = class
public
  procedure Bar;
end;
...
...
procedureTKlasseB.Bar;
begin
  A.Foo(this);
end;


Andere option, erstell ne struckt die alle infos enthält die du beim aufruf benötigst und übergib die (als const falls möglich, sonst wird sie kopiert, was teuer werden kann).

Aber, du solltest niemals vom unterliegenden Source code ausgehen. Denn wenn der kompilier optimiert gibts keine infos mehr wie der code vorher aussah. Beispiel du hast eine funktion die nur 1 zeile ausführt. Warum sollte der compiler dafür einen funktionsaufruf generieren wenn er einfach die zeile stattdessen reinkopieren kann (inlining). Damit ist nachzuschauen woher ein call kam praktisch unmöglich
Warf
 
Beiträge: 1182
Registriert: 23. Sep 2014, 17:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon TT73GP7 » 7. Jun 2019, 08:28 Re: von wo wird die Procedure aufgerufen?

fliegermichl hat geschrieben:
TT73GP7 hat geschrieben:wenn ich nun auf der Unit b die Funktion auf der Unit A aufrufe
, möchte ich gerne ein Feld aus der DataSource von der Unit A auslesen
sprich DataSource.Dataset.FieldbyName('ID').ASString;

wie komme ich denn da ran?


a.Datasource.Dataset.FieldbyName('ID').AsString;



ja der Weg ist mir bekannt
aber da ist ja die Sache das ich ja garnicht weiß das die Funktion von UnitB von der UnitA aufgerufen wurde ;)

die Funktion hätte ja ach von UnitC oder UnitE augerufen werden können
ich weiß nur das jede Unit eine DataSource drauf hat

aber ich weiß noch nicht einmal wie die DataSource heißt ;)
TT73GP7
 
Beiträge: 232
Registriert: 29. Mär 2016, 20:45

Beitragvon TT73GP7 » 7. Jun 2019, 08:38 Re: von wo wird die Procedure aufgerufen?

Warf hat geschrieben:
fliegermichl hat geschrieben:Wenn Dein Programm mit Debuginformationen compiliert wurde, kannst Du GetStackTrace verwenden.


Das das programm immer mit debuginformationen geliefert werden muss halte ich persönlich für eine herzlich beschissene idee. Der debug code in LCL programmen macht größenunterschiede im MB bereich aus. Außerdem schränkt das optimierungen (Namentlich inlining) extrem ein. Einfach nein!

Es gibt zwar andere möglichkeiten, z.B. könntest du unter den funktionsaufruf ein goto label setzen (damit kann es auch nicht wegoptimiert werden) und dann checken ob die returnaddresse die addresse von dem label ist. Das willst du aber eigentlich nicht machen.

Was man normalerweise macht ist z.B. der Sender Parameter in LCL events. Wenn ein Button geklickt wird wird der Event handler aufgerufen. Damit der weiß welcher button geklick wird, wird ihm die sender variable von TObject übergeben über die er das aufrufende Objekt identifizieren kann.

Wenn du dein programm eh OOP strukturiert hast (was ich bei Object Pascal wohl mal hoffen darf), solltest du die funktion eh aus einem anderen Objet aufrufen.
Beispiel:
Code: Alles auswählen
// UnitA:
TKlasseA = class
public
  procedure Foo(Sender: TObject);
end;
...
implementation
  uses UnitB;
...
procedureTKlasseA.Foo(Sender: TObject);
begin
  if (Sender is TKlasseB) then
    // Mach was mit (Sender as TKlasseB)
end;
 
// Unit B
uses UnitA;
...
TKlasseB = class
public
  procedure Bar;
end;
...
...
procedureTKlasseB.Bar;
begin
  A.Foo(this);
end;


Andere option, erstell ne struckt die alle infos enthält die du beim aufruf benötigst und übergib die (als const falls möglich, sonst wird sie kopiert, was teuer werden kann).

Aber, du solltest niemals vom unterliegenden Source code ausgehen. Denn wenn der kompilier optimiert gibts keine infos mehr wie der code vorher aussah. Beispiel du hast eine funktion die nur 1 zeile ausführt. Warum sollte der compiler dafür einen funktionsaufruf generieren wenn er einfach die zeile stattdessen reinkopieren kann (inlining). Damit ist nachzuschauen woher ein call kam praktisch unmöglich



hach joar kann man so machen.
Aber ich will mal etwas ausholen,
was habe ich eigentlich genau vor.

Ich will mir eigentlich viel Tipparbeit in meinen Projekten Sparen.

Es gibt Funktionen/Prozeduren die Zeilen einer Tabelle Editieren oder Öffnen etc.
FEdit(a.Datasource.dataset.fieldbyname('ID').asstring, Tabellenname);

da Öffnet sich dann ein Formular wo ich für eine Zeile alle Datensätze ändern kann.
da frage ich mich wenn ich doch weiß von wo ich das aufrufe.
dann Weiß ich doch auch welche Tabelle bzw welchen Satz (ID) einer Tabelle ich ändern will.

also Ziel ist es das ich nur noch FEdit(); aufrufe.

klar ist nicht super wichtig.
Ist auch nur Neugierde bei mir.

Aber da weiß ich noch nicht wie ich das angehe.
TT73GP7
 
Beiträge: 232
Registriert: 29. Mär 2016, 20:45

Beitragvon fliegermichl » 7. Jun 2019, 10:41 Re: von wo wird die Procedure aufgerufen?

TT73GP7 hat geschrieben:also Ziel ist es das ich nur noch FEdit(); aufrufe.


Dann übergib doch deiner Edit Prozedur die DataSource als Parameter.
Der Edit Prozedur kann es doch egal sein woher sie aufgerufen wurde.
fliegermichl
Lazarusforum e. V.
 
Beiträge: 365
Registriert: 9. Jun 2011, 09:42

• Themenende •

Zurück zu Freepascal



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast

cron
porpoises-institution
accuracy-worried