Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Tutorials und Kurse (https://www.delphipraxis.net/36-tutorials-und-kurse/)
-   -   [Artikel] Callback-Funktionen (https://www.delphipraxis.net/66528-%5Bartikel%5D-callback-funktionen.html)

Luckie 30. Mär 2006 22:32


[Artikel] Callback-Funktionen
 
In diesem Artikel geht es um Callback-Funktionen was sie sind, wie sie funktionieren und wann man sie einsetzen kann.

Link zum Artikel: Callback-Funktionen

Elvis 31. Mär 2006 00:44

Re: [Artikel] Callback-Funktionen
 
Ich finde den Artikel eigentlich nicht so gut.
Du zeigst dort als Beispiel einen Pointer, der auf einen versteckten Funktionszeigertyp geboxt wird, als sei das normale oder sogar gern gesehene Praxis.
Wenn du davon ausgehst, dass dein CallBack einen Integer bekommt und ein boolean zurückliefern muss, dann _solltest_ du nur passende CallBacks zu lassen.

Aus dem hier:
Delphi-Quellcode:
procedure DoSomething(cb: Pointer); stdcall;
var
  i: Integer;
  CallBackProc: function(i: Integer): Boolean; stdcall;
begin
  if Assigned(cb) then
  begin
    @CallBackProc := cb;
    for i := 0 to 9 do
      if not CallBackProc(i) then
        break;
  end;
end;
...würde das werden:
Delphi-Quellcode:
type TCallBackProc = function(i: Integer): Boolean;
procedure DoSomething(CallBackProc: TCallBackProc);
var
  i: Integer;
begin
  if Assigned(CallBackProc) then
  begin
    for i := 0 to 9 do
      if not CallBackProc(i) then
        break;
  end;
end;
Oder hier ein kleines kompilierbares Beispiel, das auch Funktionszeiger zeigt, die auf einer Instanz sitzen (TAddItem). Das ist die gleiche Methode in der Delphis "Events" funktionieren.

Delphi-Quellcode:
program Delegates;

{$APPTYPE CONSOLE}

uses
   Contnrs,
   SysUtils;

   type
      TSample = class
      private
         fValue: string;
      public
         property Value : string read fValue write fValue;
      end;

      TAddItem = function(item : TObject) : Integer of object;

function Compare(const left, right: TSample): Integer;
begin
   if Assigned(left) and Assigned(right) then
      Result := AnsiCompareStr(left.Value, right.Value)
   else if Assigned(left) then
      Result := 1
   else if Assigned(right) then
      Result := -1
   else
      Result := 0;
end;


var
   list   : TObjectList;
   i      : Integer;
   addItem : TAddItem;

   function Add(const value : string) : TSample;
   begin
      Result := TSample.Create();
      Result.Value := value;

      addItem(Result);
   end;
begin
   list := TObjectList.Create();
   try
      addItem := list.Add;

      Add('E');
      Add('C');
      Add('d');
      Add('a');
      Add('b');

      list.Sort(@Compare);

      for i := 0 to list.Count - 1 do
         Writeln(TSample(list[i]).Value);
   finally
      list.Free();
   end;

end.
Einfach mit F7 durchhüpfen, dann sollte klar sein was passiert. ;)

Luckie 31. Mär 2006 00:51

Re: [Artikel] Callback-Funktionen
 
Ja, den Prototypen nicht versteckt zu deklarieren, wäre wohl besser. Ich werde das mal ändern. Aber wie machen das API-Funktionen?

NicoDE 31. Mär 2006 08:15

Re: [Artikel] Callback-Funktionen
 
Ist wahrscheinlich eine Geschmacksfrage, aber ich hätte erst ein allgemeines Problem beschrieben und dann die Entwicklung des Lösungsansatzes an einem Beispiel verdeutlicht.

Zum Beispiel:
(Frage) Wie kann eine allgemeine Basisklasse wie TList die enthaltenen Einträge sortieren ohne deren Inhalt zu kennen?
(Ansatz) TList muss den Aufrufer fragen -> Der Aufrufer muss also eine Funktion bereitstellen die 'zurückgerufen' wird.

Nachdem das Prinzip verstanden ist, kann man zu weiteren Beispielen kommen (Aufzählungen, Fortschrittsanzeigen, etc.).
Der dritte Punkt (Zitat aus dem anderen Thread) war als Scherz gemeint; und hat im Tutorial nichts zu suchen...

shmia 31. Mär 2006 09:17

Re: [Artikel] Callback-Funktionen
 
Zitat:

Übrigens, Ereignisse, wie man sie aus der objektorientierten Programmierung kennt, sind im Endeffekt auch nichts anderes als Callback-Funktionen. In Delphi übergibt man die Adresse einer Methode und die VCL bzw. Klasse, welche das Ereignis implementiert, ruft sie dann auf. Eben wie es mit unserer Callback-Funktion geschiet. Eine alte Technik im neuen Gewand sozusagen.
Ich würde eher so schreiben:
Ereignisse, wie man sie aus der objektorientierten Programmierung kennt, sind den Callback-Funktionen ähnlich. Allerdings enthält ein Methodenzeiger zusätzlich noch einen Zeiger auf das Objekt (benötigt also 64 Bit).
Der Eventhandler bekommt den Zeiger auf das Objekt als verborgenen self-Zeiger mit.
Damit sind Eventhandler den normalen Callback-Funktionen überlegen und können einfacher verwendet werden.

Luckie 31. Mär 2006 09:23

Re: [Artikel] Callback-Funktionen
 
@shmia. Danke. Klingt besser. Werde ich so übernehmen.

Ich habe übrigens die Anmerkungen von Nico im anderen Thread einfließen lassen.

brechi 31. Mär 2006 09:23

Re: [Artikel] Callback-Funktionen
 
Noch ein paar Funktionen die bekannt sind und Callbacks brauchen:

user32.SetTimer
kernel32.CreateThread (BeginThread)

Und es gibt eine 3. Möglichkeit neben dynamischen Arrays und Callbackfunktionen soetwas zu erstellen.
Dort kann man auch die Funktion abbrechen und zusätzlich selbst bestimmten wann 'weitergearbeitet' wird.

Siehe z.b. Process32First / Process32Next.

xaromz 31. Mär 2006 09:28

Re: [Artikel] Callback-Funktionen
 
Hallo,
Zitat:

Zitat von shmia
Methodenzeiger zusätzlich noch einen Zeiger auf das Objekt (benötigt also 64 Bit).

Nicht ganz. Der Self-Zeiger wird als zusätzliches Argument übergeben, da ist nix mit 64 Bit.
Zitat:

Zitat von shmia
Damit sind Eventhandler den normalen Callback-Funktionen überlegen und können einfacher verwendet werden.

Sie sind nicht überlegen, sie sind für einen anderen Zweck. Ich kann auch einer "klassischen" Callback-Funktion einen Zeiger auf ein Objekt mitgeben. Schau Dir mal die Callback-Funktion "TStringListSortCompare" an. Da wird im ersten Parameter eine StringList übergeben.

Gruß
xaromz

Motzi 31. Mär 2006 09:32

Re: [Artikel] Callback-Funktionen
 
@Luckie: schau dir mal mein Pointer-Tutorial an, da schreib ich auch was über Funktionszeiger, Methodenzeiger und Callback-Funktionen und im Demo-Prog dazu (implementierung einer Double-Linked-List) gibt es eine Sortier-Funktion die mit einer Callback-Funktion arbeitet. Vielleicht hilft dir das..


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:39 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz