Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Was ist eine Callback Funktion (https://www.delphipraxis.net/66456-ist-eine-callback-funktion.html)

Luckie 29. Mär 2006 22:18


Was ist eine Callback Funktion
 
Also ich kenne sie und benutze sie auch zum Beispiel bei EnumWindows. Aber wie funktioniert eine Callback Funktion eigentlioch genau. Ich habe da mal was geschrieben:
Delphi-Quellcode:
type
  TCallBack = function(i: Integer): Boolean; stdcall;

function CallBack(i: Integer): Boolean; stdcall;
begin
  ShowMessage(IntToStr(i));
end;

procedure DoSomething(cb: TCallBack);
var
  i: Integer;
begin
  if Assigned(cb) then
  begin
    for i := 0 to 9 do
      CallBack(i);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  DoSomething(CallBack);
end;
Wäre das eine Callback Funktion oder habe ich da was falsch verstanden und wenn ja, wie geht es richtig?

brechi 29. Mär 2006 22:22

Re: Was ist eine Callback Funktion
 
Jo is schon so fast richtig.

Bei APIs hast du eigentlich nur einen Pointer, d.h. es sieht in etwa so aus:

Delphi-Quellcode:

function CallBack(i: Integer): Boolean; stdcall;
begin
  ShowMessage(IntToStr(i));
end;

procedure DoSomething(cb: Pointer); stdcall; //das wäre die API
var
  i: Integer;
  CallBack: function(i: Integer): Boolean; stdcall;
begin
  if Assigned(cb) then
  begin
    @CallBack := cb;
    for i := 0 to 9 do
      CallBack(i);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  DoSomething(@CallBack); // aufruf der API mit der callback funtion als pointer
end;

alcaeus 29. Mär 2006 22:24

Re: Was ist eine Callback Funktion
 
Eine Callback-Funktion ist eine Funktion, die du sozusagen uebergeben kannst. Nehmen wir an, deine Callback-Funktion heisst CB(), deine andere Funktion foo(). Callback bedeutet nun, dass du foo() aufrufst und deine Callback-Funktion uebergibst. foo() wird dann irgendwann deine Callback-Funktion mit vorbestimmten Parametern aufrufen. Deine Funktion macht dann was und gibt irgendwas zurueck. Dies wird wiederum von foo() verwendet.
Das nur um mal eine trockene Erklaerung zu bringen :lol:

Greetz
alcaeus

Luckie 29. Mär 2006 22:30

Re: Was ist eine Callback Funktion
 
Danke Jungs, wieder was gelernt.

@brechi: Jupp, das sieht schon eher richtig aus. ;)

Wann setzt man denn eigentlich eine Callback Funktion ein? Also ich würde sie einsetzen, wenn ich eigentlich ein dynamisches Array zurückgeben müsste, dies aber nicht will oder kann. Stattdessen übergebe ich eine Funktion, der ich dann die Elemente einzeln übergebe und der Nutzer sie dann in der Callback Funktion selber weiterverarbeiten kann. Wäre das ein Einatzgebiet?

Zum Beispiel habe ich in MpuNTUser.pas eine Funktion EnumUsers, die alle Benutzer in einem dynamischen Array zurückgibt, dort könnte ich ja dann eine Callback Funktion nutzen, um das dynamische Array zu vermeiden. Richtig?

Flocke 29. Mär 2006 23:00

Re: Was ist eine Callback Funktion
 
Zitat:

Zitat von Luckie
Wann setzt man denn eigentlich eine Callback Funktion ein? Also ich würde sie einsetzen, wenn ich eigentlich ein dynamisches Array zurückgeben müsste, dies aber nicht will oder kann. Stattdessen übergebe ich eine Funktion, der ich dann die Elemente einzeln übergebe und der Nutzer sie dann in der Callback Funktion selber weiterverarbeiten kann. Wäre das ein Einatzgebiet?

Zum Beispiel habe ich in MpuNTUser.pas eine Funktion EnumUsers, die alle Benutzer in einem dynamischen Array zurückgibt, dort könnte ich ja dann eine Callback Funktion nutzen, um das dynamische Array zu vermeiden. Richtig?

Das ist ein sehr gutes Beispiel, wie es z.B. auch viele API-Funktionen, die mit "Enum" beginnen, nutzen (EnumDisplayMonitors, EnumFonts, EnumFontFamilies, EnumWindows, usw.). Um diese Funktionalität auch aus Programmiersprachen heraus nutzen zu können, die nicht mit Interfaces arbeiten können (IEnum...) oder keine dynamischen Arrays kennen, nimmt man dort oft Callbacks.

Ein weiteres häufiges Einsatzgebiet ist die Prüfung auf Abbruch, z.B. bei einem Druck- oder Kopierdialog. Dadurch ermöglich man zum einen ein "ProcessMessages" (die Aktualisierung des Fensters), zum anderen hat der User halt auch die Möglichkeit des Abbruchs, ohne dass deine Implementierung der Druck- oder Kopierfunktion über die Details Bescheid wissen muss.

Luckie 29. Mär 2006 23:02

Re: Was ist eine Callback Funktion
 
OK. Gut. Allerdings wie das mit dem Abbrechen funktionieren soll, habe ich jetzt nicht ganz verstanden. Hättest du da etwas Beispiel Code zur Demonstration zur Hand?

Ich drohe an dieser Stelle schon mal mit meinem nächsten Artikel. :mrgreen:

sniper_w 29. Mär 2006 23:06

Re: Was ist eine Callback Funktion
 
Zitat:

Zitat von Luckie
Also ich kenne sie und benutze sie auch zum Beispiel bei EnumWindows. Aber wie funktioniert eine Callback Funktion eigentlioch genau. Ich habe da mal was geschrieben:
Delphi-Quellcode:
type
  TCallBack = function(i: Integer): Boolean; stdcall;

function CallBack(i: Integer): Boolean; stdcall;
begin
  ShowMessage(IntToStr(i));
end;

procedure DoSomething(cb: TCallBack);
var
  i: Integer;
begin
  if Assigned(cb) then
  begin
    for i := 0 to 9 do
      CallBack(i);// <<---- sniper_w : FEHLER , kein Callback
      // cb(i); <<<---sniper_w: so ist richtig
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  DoSomething(CallBack);// <<-- sniper_w: FEHLER
  DoSomething(@CallBack);// <<-- sniper_w: richtig, weil TCallback erwartet wird und das ist ein Funktions-POINTER
end;
Wäre das eine Callback Funktion oder habe ich da was falsch verstanden und wenn ja, wie geht es richtig?


Luckie 29. Mär 2006 23:08

Re: Was ist eine Callback Funktion
 
Du bist etwas spät dran sniper_w. ;)

Flocke 29. Mär 2006 23:17

Re: Was ist eine Callback Funktion
 
Zitat:

Zitat von Luckie
OK. Gut. Allerdings wie das mit dem Abbrechen funktionieren soll, habe ich jetzt nicht ganz verstanden. Hättest du da etwas Beispiel Code zur Demonstration zur Hand?

Ist jetzt zwar nicht eine Funktion, aber du kannst beim Drucken mit "SetAbortProc" eine Callback-Funktion setzen, die dann vom System periodisch aufgerufen wird und den Druckvorgang jederzeit abbrechen kann. Delphi nutzt das selbst in der Unit Printers.pas.

Ein anderes Beispiel finde ich jetzt gerade nicht, wobei ich eigentlich noch irgendwas mit Kopieren im Kopf habe...

Luckie 29. Mär 2006 23:21

Re: Was ist eine Callback Funktion
 
Jupp, da war was: MSDN-Library durchsuchenCopyFileEx. ;)

Gibt es sonst noch was interessantes, was man dazu sagen könnte?

xaromz 29. Mär 2006 23:55

Re: Was ist eine Callback Funktion
 
Hallo,
Zitat:

Zitat von Luckie
Gibt es sonst noch was interessantes, was man dazu sagen könnte?

Viele Callback-Funktionen sind tatsächlich Funktionen, d. h. sie können zurückliefern, ob es weitergeht oder abgebrochen/beendet werden soll.

Gruß
xaromz

Luckie 29. Mär 2006 23:57

Re: Was ist eine Callback Funktion
 
Jupp, habe mein Beispiel gerade dahingehen angepasst. Morgen in der Mittagspause, werde ich mal einen kurzen Artikel dazu schreiben. Denn ich glaube, den meisten geht es wie mir, die dachten, dass hinter Callback Funktionen irgend was geheimnisvolles von Windows steckt. ;)

xaromz 30. Mär 2006 00:02

Re: Was ist eine Callback Funktion
 
Hallo,
Zitat:

Zitat von Luckie
Denn ich glaube, den meisten geht es wie mir, die dachten, dass hinter Callback Funktionen irgend was geheimnisvolles von Windows steckt. ;)

Wo doch Callback-Funktionen viiiel älter als Windows sind, damit hab ich ja schon unter DOS gearbeitet :wink: . Wurde da (und wird immer noch) in Soundbrecih benutzt. Irgendwie muss man ja aufgenommene Sounds auch speichern. Und da übergibt eben der Soundtreiber den Puffer an... na, ihr kommt selbst drauf :stupid:

Gruß
xaromz

Luckie 30. Mär 2006 00:06

Re: Was ist eine Callback Funktion
 
Ja OK. Aber ich kenne sie nur von Windows.

Aber belieb wir mal bei meinem Beispiel: dynamisches Array vs. Callback Funktion. Ich tendiere langsam zur Callback Funktion, weil man da dem Aufrufer eine gewisse Kontrolle gibt. (Er kann entscheiden, wann abgebrochen werden soll oder nicht.) Gibt es noch mehr Pro / Contra dynamisches Array - Callback Funktion?

Zum Beispiel könnte man damit dies Problem lösen: http://www.delphipraxis.net/internal...ct.php?t=79239
Man list beide Namen aus dem Record aus und wenn der Name mit GetUsername übereinstimmt, bricht man ab und nimmt den vollständigen Namen.

sECuRE 30. Mär 2006 05:32

Re: Was ist eine Callback Funktion
 
Hi,

Zitat:

Zitat von Luckie
Ja OK. Aber ich kenne sie nur von Windows.

Ich kenne Callbackfunktionen auch unter Linux, speziell im Einsatzgebiet von zum Beispiel einer FTP-Library/Toolkit (macht auch bei anderen Protokollen, wie zum Beispiel dem IRC, Sinn). Dort kannst du eine Callbackfunktion übergeben, die zum Beispiel bei der nächsten Antwort, die den Code 200 hat, aufgerufen wird. Das ist sinnvoll, da die Antworten zwar immer gleich sind (200 ist generell eine Bestätigung), aber in verschiedenen Kontexten gebraucht werden...

cu

NicoDE 30. Mär 2006 07:50

Re: Was ist eine Callback Funktion
 
Callback-Funktionen/Methoden sind IMHO immer dann nützlich, wenn

a) gegenseitige Abhängigkeiten in allgemeinen APIs aufgelöst werden müssen
(DoSomething muss nichts über das benutzende Programm wissen)

b) der Fortschritt beeinflusst werden kann
(insbesondere bei Aufzählungen)

c) man Entwickler mit unnötiger Abstraktion ärgern will ;)

Luckie 30. Mär 2006 08:10

Re: Was ist eine Callback Funktion
 
Gut. Allerdings würde man heutzutage wohl, um OOP konform zu sein eher mit Events arbeiten oder?

xaromz 30. Mär 2006 08:16

Re: Was ist eine Callback Funktion
 
Hallo,
Zitat:

Zitat von Luckie
Gut. Allerdings würde man heutzutage wohl, um OOP konform zu sein eher mit Events arbeiten oder?

Die Events, welche Delphi implementiert, sind ja so eine Art Callback-Funktionen: Du übergibst die Adresse einer Methode und die VCL ruft sie auf, wenn es nötig ist.

Gruß
xaromz

Luckie 30. Mär 2006 08:32

Re: Was ist eine Callback Funktion
 
Stimmt auch wieder. Also Callbacks nur neu verpackt. ;)

NicoDE 30. Mär 2006 17:03

Re: Was ist eine Callback Funktion
 
Zitat:

Zitat von Luckie
Gut. Allerdings würde man heutzutage wohl, um OOP konform zu sein eher mit Events arbeiten oder?

Wenn du damit Methoden meinst (of object), dann kann man dies auch in nicht-OOP-APIs durch die Übergabe eines weiteren Parameters erreichen (Handles in C-APIs sind oft nicht anderes als Referenzen auf interne C++-Objekte).

sniper_w 30. Mär 2006 20:26

Re: Was ist eine Callback Funktion
 
Zitat:

(Handles in C-APIs sind oft nicht anderes als Referenzen auf interne C++-Objekte).
Daran zweifle ich stark. Das sind eher die "ID-s", die dafür benuzt werden, die entsprechende Objekte ( sei es c++ "classes" oder "noramle struct" Gebilde) in einer Tabele(von Windows verwaltet, versteht sich) zu finden.
Hättest du recht, wäre das IMO eine potenzielle Sicherkeitslücke.

NicoDE 30. Mär 2006 20:40

Re: Was ist eine Callback Funktion
 
Zitat:

Zitat von sniper_w
Zitat:

(Handles in C-APIs sind oft nicht anderes als Referenzen auf interne C++-Objekte).
Daran zweifle ich stark. Das sind eher die "ID-s", die dafür benuzt werden, die entsprechende Objekte ( sei es c++ "classes" oder "noramle struct" Gebilde) in einer Tabele(von Windows verwaltet, versteht sich) zu finden.
Hättest du recht, wäre das IMO eine potenzielle Sicherkeitslücke.

Ich rede nicht von Windows APIs... :)
(sondern von Projekten die in C++ entwickelt werden und als kleinsten gemeinsamen Nenner eine flache "C"-API anbieten müssen)

sniper_w 30. Mär 2006 20:47

Re: Was ist eine Callback Funktion
 
Zitat:

Zitat von NicoDE
Ich rede nicht von Windows APIs... :)
(sondern von Projekten die in C++ entwickelt werden und als kleinsten gemeinsamen Nenner eine flache "C"-API anbieten müssen)

Insofern hast völlig recht :wink:

Luckie 30. Mär 2006 22:34

Re: Was ist eine Callback Funktion
 
So, ich habe das hier noch mal alles in einem Artikel auf meiner Homepage zusammengefasst: Callback-Funktionen. ich hoffe es ist korrekt und einigermaßen verständlich erklär.

Der entsprechende Thread in der Tutorialsparte: http://www.delphipraxis.net/internal...ct.php?t=79464

Oxmyx 30. Mär 2006 22:56

Re: Was ist eine Callback Funktion
 
Rückruffunktionen werden auch bei Sortierverfahren eingesetzt. Beispiel: Ich will einen ganzen Haufen TAutos sortieren. Meine Sortierfunktion kann natürlich nicht wissen, nach welchen Kriterien ich meine Autos sortiert haben will, also übergebe ich eine Funktion, um diese Entscheidung zu treffen.

Luckie 30. Mär 2006 23:22

Re: Was ist eine Callback Funktion
 
Ah, sehr schöne Ergänzung.

runger 31. Mär 2006 07:16

Re: Was ist eine Callback Funktion
 
Hallo Luckie,

ich bin etwas verwirrt, bei mir funktioniert das hier nicht:

Delphi-Quellcode:
  DoSomething(@Callback);
sondern nur das:
Delphi-Quellcode:
  DoSomething(Callback);
Fehler? Oder was mach ich falsch. Dem allgemeinen Verständnis nach müsste deine Version richtig sein.

Rainer

Luckie 31. Mär 2006 07:27

Re: Was ist eine Callback Funktion
 
Bei mir funktioniert beides. :shock: Aber eigentlich sollte, wenn ich es mir genau überlege, nach Elvis Methode nur zweitere funktionieren, da kein Zeiger mehr erwartet wird.

Eventuell sollte man es so machen:
Delphi-Quellcode:
function CallBack(i: Integer): Boolean; stdcall;
begin
  result := True;
  ShowMessage(IntToStr(i));
  if i = 5 then
    result := False;
end;

type
  TCallbackProc = function(i: Integer): Boolean; stdcall;
  PCallbackProc = ^TCallbackProc;

procedure DoSomething(cbp: PCallbackProc); stdcall;
var
  i: Integer;
  CallbackProc: TCallbackProc;
begin
  if Assigned(cbp) then
  begin
    @CallbackProc := cbp;
    for i := 0 to 9 do
      if not CallBackProc(i) then
        break;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  DoSomething(@Callback);
end;

NicoDE 31. Mär 2006 07:53

Re: Was ist eine Callback Funktion
 
Zitat:

Zitat von Luckie
Bei mir funktioniert beides.

Hängt vom jeweiligen Compiler und dessen aktuellen Optionen ab.
Dadurch entstehen Codefragmente wie dieses:
Delphi-Quellcode:
DllProcNext := TDLLProc(DllProc);
TDLLProc(DllProc) := LibraryProc;

Luckie 31. Mär 2006 08:20

Re: Was ist eine Callback Funktion
 
Wie wäre es denn jetzt korrekt? Bzw. wie macht es Windows? Da wird ja auch immer ein zeiger erwartet.

NicoDE 31. Mär 2006 08:35

Re: Was ist eine Callback Funktion
 
Zitat:

Zitat von Luckie
Wie wäre es denn jetzt korrekt?

Typsicher und ohne Adressoperator (Delphi sorgt implizit dafür, dass die Adresse übergeben wird).

In der Praxis kommt es leider vor, dass die Typen in den verschiedenen Delphi-Versionen unterschiedlich deklariert sind. In dem Fall werden (links- und/oder rechts) explizite Typkonvertierungen notwendig (was die Typsicherheit von Delphi leider ad absurdum führt...).
Den Adressoperator würde ich, wann immer möglich, vermeiden.

Zitat:

Zitat von Luckie
Bzw. wie macht es Windows? Da wird ja auch immer ein zeiger erwartet.

Das kommt auf die Übersetzung des Headers an... wenn die Parameter nicht als Funktionsprototypen deklariert sind, kommt man leider nicht ohne Typkonvertierungen und/oder den Adressoperator aus.
In eigenen Schnittstellen sollte dies allerdings nicht vorkommen.

Luckie 31. Mär 2006 08:58

Re: Was ist eine Callback Funktion
 
So, habe es mal korrigiert und entsprechend angepasst.

Luckie 22. Apr 2006 12:45

Re: Was ist eine Callback Funktion
 
Ich überarbeite gerade meine Unit MpuNTU.pas mit ihren Callback-Funktionen. Dabei erweitere ich die eigentliche Funktion, um einen zusätzlichen Parameter, damit der Benutzer der Callback-Funktion weitere, beliebige Daten mitgeben kann. Das sieht dann so aus:

Delphi-Quellcode:
type
  PMyEnumParam = ^TMyEnumParam;
  TMyEnumParam = record
    lb: TListbox;
  end;

function EnumUserCallback(Username: string; cntUsers: Integer; Data: Pointer): Boolean;
begin
  PMyEnumParam(Data)^.lb.Items.Add(Username);
  Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Param: TMyEnumParam;
begin
  Param.lb := Listbox1;
  EnumUsers('', FILTER_NORMAL_ACCOUNT, EnumUserCallback, @Param);
end;
Jetzt meine Frage. EnumWindows macht es genauso, nur da ist der zusätzliche Parameter als LPARAM, also Cardinal, deklariert, ich verwende als Datentyp einen Pointer, weil ich dachte, da kann ich alles reinstopfen und wer weiß, was ein zukünftiger Benutzer der Unit damit machen will. Allerdings könnte man einen Pointer auch zu einem Integer casten, wie man es bei EnumWindow machen würde, wenn man obiges Beispiel nimmt. Ist das halo gehupft wie gesprungen oder was spricht für einen Pointer bzw. Integer?

Luckie 23. Apr 2006 13:39

Re: Was ist eine Callback Funktion
 
Hat da niemand eine Meinung zu?

sniper_w 23. Apr 2006 13:51

Re: Was ist eine Callback Funktion
 
Ich denke, dass ein Integer besser passen würde wegen portabilitet.

Am sonsten, was Delphi betrifft, ist es egal, denn man kan einen Integer zum Pointer machen und umgekehrt.

xaromz 23. Apr 2006 13:54

Re: Was ist eine Callback Funktion
 
Hallo,
Zitat:

Zitat von Luckie
was spricht für einen Pointer bzw. Integer?

die aktuelle Befindlichkeit :mrgreen: .
Im Ernst, das ist Geschmackssache. Ein Pointer ist immer genauso groß wie ein Integer, also sind die beiden austauschbar. Die Frage ist, was wird vermutlich verwendet? Wenn ein Programmierer in der Situation öfter einen Integer übergeben möchte, so deklariert man auch einen Integer. Ist ein Pointer wahrscheinlicher, nimmt man eben auch einen Pointer. Hat man keine Ahnung, dann ist es auch egal.

Gruß
xaromz

Hawkeye219 23. Apr 2006 14:11

Re: Was ist eine Callback Funktion
 
Hallo Luckie,

ich bin für Pointer, das klingt etwas allgemeiner als Integer. Bei einem Integer-Parameter könnte man ja davon ausgehen, daß man durch unterschiedliche Werte das Verhalten der aufrufenden Routine steuern kann. Dies ist aber nicht der Fall, da sie den Wert unverändert an die Callback-Routine übergeben soll.

Gruß Hawkeye

Luckie 23. Apr 2006 14:25

Re: Was ist eine Callback Funktion
 
Ich denke auch, dass ich bei Pointer bleiben werde, da das mehr nach benutzerspezifischen Daten klingt.[xml]

BlackJack 23. Apr 2006 14:54

Re: Was ist eine Callback Funktion
 
Zitat:

Zitat von Oxmyx
Rückruffunktionen werden auch bei Sortierverfahren eingesetzt. Beispiel: Ich will einen ganzen Haufen TAutos sortieren. Meine Sortierfunktion kann natürlich nicht wissen, nach welchen Kriterien ich meine Autos sortiert haben will, also übergebe ich eine Funktion, um diese Entscheidung zu treffen.

z.b. TList macht das auch so: wenn du TList.Sort() aufrufst, musst du als parameter eine Funktion übergeben, und diese funktion bekommt dann nachher beim sortieren die Pointer auf zwei Elemente, die du dann vergleichst und dementsprechend einen bestimmten rückgabewert zurückgibst (-1, 0 oder 1).


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:19 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