AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Tutorials [Artikel] Callback-Funktionen
Tutorial durchsuchen
Ansicht
Themen-Optionen

[Artikel] Callback-Funktionen

Ein Tutorial von Luckie · begonnen am 30. Mär 2006 · letzter Beitrag vom 31. Mär 2006
Antwort Antwort
Benutzerbild von Luckie
Luckie
Registriert seit: 29. Mai 2002
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
Ein Teil meines Codes würde euch verunsichern.
 
Elvis

 
Delphi 2010 Professional
 
#2
  Alt 31. Mär 2006, 00:44
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.
Robert Giesecke
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

 
Delphi 2006 Professional
 
#3
  Alt 31. Mär 2006, 00:51
Ja, den Prototypen nicht versteckt zu deklarieren, wäre wohl besser. Ich werde das mal ändern. Aber wie machen das API-Funktionen?
Michael
  Mit Zitat antworten Zitat
NicoDE
 
#4
  Alt 31. Mär 2006, 08:15
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...
  Mit Zitat antworten Zitat
shmia

 
Delphi 5 Professional
 
#5
  Alt 31. Mär 2006, 09:17
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.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

 
Delphi 2006 Professional
 
#6
  Alt 31. Mär 2006, 09:23
@shmia. Danke. Klingt besser. Werde ich so übernehmen.

Ich habe übrigens die Anmerkungen von Nico im anderen Thread einfließen lassen.
Michael
  Mit Zitat antworten Zitat
brechi
 
#7
  Alt 31. Mär 2006, 09:23
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.
  Mit Zitat antworten Zitat
xaromz

 
Delphi 2006 Enterprise
 
#8
  Alt 31. Mär 2006, 09:28
Hallo,
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 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
  Mit Zitat antworten Zitat
Benutzerbild von Motzi
Motzi

 
Delphi XE2 Professional
 
#9
  Alt 31. Mär 2006, 09:32
@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..
Manuel Pöter
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:10 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz