von wo wird die Procedure aufgerufen?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
TT73GP7
Beiträge: 238
Registriert: Di 29. Mär 2016, 20:45

von wo wird die Procedure aufgerufen?

Beitrag von TT73GP7 »

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

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: von wo wird die Procedure aufgerufen?

Beitrag von fliegermichl »

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

Frank Ranis
Beiträge: 201
Registriert: Do 24. Jan 2013, 21:22

Re: von wo wird die Procedure aufgerufen?

Beitrag von Frank Ranis »

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

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: von wo wird die Procedure aufgerufen?

Beitrag von fliegermichl »

Ja das ist doof. Ich habe Lazarus 1.8.5 und da ist das noch in LCLProc

TT73GP7
Beiträge: 238
Registriert: Di 29. Mär 2016, 20:45

Re: von wo wird die Procedure aufgerufen?

Beitrag von TT73GP7 »

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.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: von wo wird die Procedure aufgerufen?

Beitrag von fliegermichl »

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;

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: von wo wird die Procedure aufgerufen?

Beitrag von Warf »

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

TT73GP7
Beiträge: 238
Registriert: Di 29. Mär 2016, 20:45

Re: von wo wird die Procedure aufgerufen?

Beitrag von TT73GP7 »

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: 238
Registriert: Di 29. Mär 2016, 20:45

Re: von wo wird die Procedure aufgerufen?

Beitrag von TT73GP7 »

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.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1430
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: von wo wird die Procedure aufgerufen?

Beitrag von fliegermichl »

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.

Antworten