C++

Callback-Funktion in C++

Callback-Funktion in C++

Eine Callback-Funktion ist eine Funktion, die ein Argument, kein Parameter, in einer anderen Funktion ist. Die andere Funktion kann als Hauptfunktion bezeichnet werden. Es sind also zwei Funktionen beteiligt: ​​die Principal-Funktion und die Callback-Funktion selbst. In der Parameterliste der Principal-Funktion ist die Deklaration der Callback-Funktion ohne ihre Definition vorhanden, ebenso wie Objektdeklarationen ohne Zuweisung vorhanden sind. Die Principal-Funktion wird mit Argumenten aufgerufen (in main()). Eines der Argumente im Hauptfunktionsaufruf ist die effektive Definition der Rückruffunktion. In C++ ist dieses Argument ein Verweis auf die Definition der Callback-Funktion; es ist nicht die eigentliche Definition. Die Callback-Funktion selbst wird tatsächlich innerhalb der Definition der Principal-Funktion aufgerufen.

Die grundlegende Callback-Funktion in C++ garantiert kein asynchrones Verhalten in einem Programm.  Asynchrones Verhalten ist der wahre Vorteil des Callback-Funktionsschemas. Beim asynchronen Callback-Funktionsschema sollte das Ergebnis der Principal-Funktion für das Programm abgerufen werden, bevor das Ergebnis der Callback-Funktion abgerufen wird. Dies ist in C++ möglich; C++ verfügt jedoch über eine Bibliothek namens future, um das Verhalten des asynchronen Callback-Funktionsschemas zu gewährleisten.

Dieser Artikel erklärt das grundlegende Schema der Rückruffunktion. Vieles davon ist mit reinem C++. Was den Callback angeht, wird auch das grundsätzliche Verhalten der zukünftigen Bibliothek erklärt. Für das Verständnis dieses Artikels sind Grundkenntnisse in C++ und seinen Pointern erforderlich.

Artikelinhalt

Grundlegendes Schema der Rückruffunktion

Ein Callback-Funktionsschema benötigt eine Principal-Funktion und die Callback-Funktion selbst. Die Deklaration der Callback-Funktion ist Teil der Parameterliste der Principal-Funktion. Die Definition der Callback-Funktion ist im Funktionsaufruf der Principal-Funktion angegeben. Die Callback-Funktion wird tatsächlich innerhalb der Definition der Principal-Funktion aufgerufen. Das folgende Programm veranschaulicht dies:

#einschließen
Verwenden von Namespace-Std;
int PrincipalFn(char ch[], int (*ptr)(int))

int-ID1 = 1;
int-ID2 = 2;
int idr = (*ptr)(id2);
cout<<"principal function: "<Rückgabe-ID1;

int cb(int ident)

cout<<"callback function"<<'\n';
Rückgabe-ID;

int main()

int (*ptr)(int) = &cb;
char cha[] = "und";
PrincipalFn(cha, cb);
0 zurückgeben;

Die Ausgabe ist:

Rückruffunktion
Hauptfunktion: 1 und 2

Die Principal-Funktion wird durch PrincipalFn() identifiziert. Die Callback-Funktion wird durch cb() identifiziert. Die Callback-Funktion wird außerhalb der Principal-Funktion definiert, aber tatsächlich innerhalb der Principal-Funktion aufgerufen.

Beachten Sie die Deklaration der Callback-Funktion als Parameter in der Parameterliste der Principal Function Deklaration. Die Deklaration der Callback-Funktion lautet „int (*ptr)(int)“. Beachten Sie den Callback-Funktionsausdruck wie einen Funktionsaufruf in der Definition der Prinzipalfunktion; jedes Argument für den Callback-Funktionsaufruf wird dort übergeben. Die Anweisung für diesen Funktionsaufruf lautet:

int idr = (*ptr)(id2);

Wobei id2 ein Argument ist. ptr ist Teil des Parameters, ein Zeiger, der mit der Referenz der Callback-Funktion in der main()-Funktion verknüpft wird.

Beachten Sie den Ausdruck:

int (*ptr)(int) = &cb;

In der Funktion main(), die die Deklaration (ohne Definition) der Callback-Funktion mit dem Namen der Definition derselben Callback-Funktion verknüpft links.

Die Hauptfunktion wird in der Funktion main() wie folgt aufgerufen:

PrincipalFn(cha, cb);

Dabei ist cha ein String und cb der Name der Callback-Funktion ohne ihre Argumente.

Synchrones Verhalten der Callback-Funktion

Betrachten Sie das folgende Programm:

#einschließen
Verwenden von Namespace-Std;
void PrincipalFn(void (*ptr)())

cout<<"principal function"<<'\n';
(*ptr)();

Leere cb()

cout<<"callback function"<<'\n';

Leere fn()

cout<<"seen"<<'\n';

int main()

Leere (*ptr)() = &cb;
HauptFn(cb);
fn();
0 zurückgeben;

Die Ausgabe ist:

Hauptfunktion
Rückruffunktion
gesehen

Hier gibt es eine neue Funktion. Die neue Funktion zeigt lediglich die Ausgabe „gesehen“ an. In der Funktion main() wird die Hauptfunktion aufgerufen, dann wird die neue Funktion fn() aufgerufen. Die Ausgabe zeigt, dass der Code für die Principal-Funktion ausgeführt wurde, dann der für die Callback-Funktion und schließlich der für die fn()-Funktion. Dies ist synchrones (Single-Thread-) Verhalten.

Bei asynchronem Verhalten, wenn drei Codesegmente der Reihe nach aufgerufen werden, kann das erste Codesegment ausgeführt werden, gefolgt von der Ausführung des dritten Codesegments, bevor das zweite Codesegment ausgeführt wird.

Nun, die Funktion fn() kann aus der Definition der Hauptfunktion heraus aufgerufen werden, anstatt aus der main()-Funktion, wie folgt:

#einschließen
Verwenden von Namespace-Std;
Leere fn()

cout<<"seen"<<'\n';

void PrincipalFn(void (*ptr)())

cout<<"principal function"<<'\n';
fn();
(*ptr)();

Leere cb()

cout<<"callback function"<<'\n';

int main()

Leere (*ptr)() = &cb;
HauptFn(cb);
0 zurückgeben;

Die Ausgabe ist:

Hauptfunktion
gesehen
Rückruffunktion

Dies ist eine Imitation von asynchronem Verhalten. Es ist kein asynchrones Verhalten. Es ist immer noch synchrones Verhalten.

Außerdem kann die Ausführungsreihenfolge des Codesegments der Principal-Funktion und des Codesegments der Callback-Funktion in der Definition der Principal-Funktion vertauscht werden. Das folgende Programm veranschaulicht dies:

#einschließen
Verwenden von Namespace-Std;
 
void PrincipalFn(void (*ptr)())

(*ptr)();
cout<<"principal function"<<'\n';

Leere cb()

cout<<"callback function"<<'\n';

Leere fn()

cout<<"seen"<<'\n';

int main()

Leere (*ptr)() = &cb;
HauptFn(cb);
fn();
0 zurückgeben;

Die Ausgabe ist jetzt,

Rückruffunktion
Hauptfunktion
gesehen

Dies ist auch eine Imitation von asynchronem Verhalten. Es ist kein asynchrones Verhalten. Es ist immer noch synchrones Verhalten. Echtes asynchrones Verhalten kann wie im nächsten Abschnitt erläutert oder mit der Bibliothek zukünftig erreicht werden.

Asynchrones Verhalten mit Callback-Funktion

Der Pseudocode für das grundlegende asynchrone Callback-Funktionsschema lautet:

Typ Ausgabe;
Typ cb (Typ Ausgang)

//Aussagen

Typ PrincipalFn (Typ Eingabe, Typ cb (Typ Ausgabe))

//Aussagen

Beachten Sie die Positionen der Ein- und Ausgabedaten an den verschiedenen Stellen des Pseudocodes. Die Eingabe der Callback-Funktion ist ihre Ausgabe. Die Parameter der Principal-Funktion sind der Input-Parameter für den Generalcode und der Parameter für die Callback-Funktion. Mit diesem Schema kann eine dritte Funktion in der main()-Funktion ausgeführt (aufgerufen) werden, bevor die Ausgabe der Callback-Funktion gelesen wird (noch in der main()-Funktion). Der folgende Code veranschaulicht dies:

#einschließen
Verwenden von Namespace-Std;
char *Ausgabe;
void cb(char out[])

Ausgang = aus;

void PrincipalFn(char input[], void (*ptr)(char[50]))

(*ptr)(Eingabe);
cout<<"principal function"<<'\n';

Leere fn()

cout<<"seen"<<'\n';

int main()

char input[] = "Rückruffunktion";
void (*ptr)(char[]) = &cb;
PrincipalFn(Eingang, Cb);
fn();
cout<0 zurückgeben;

Die Programmausgabe ist:

Hauptfunktion
gesehen
Rückruffunktion

In diesem speziellen Code sind das Ausgabe- und das Eingabedatum zufällig das gleiche Datum. Das Ergebnis des dritten Funktionsaufrufs in der main()-Funktion wurde vor dem Ergebnis der Callback-Funktion angezeigt. Die Callback-Funktion wurde ausgeführt, beendet und ihr Ergebnis (Wert) der Variablenausgabe zugewiesen, sodass das Programm ohne Störungen weiterlaufen kann. In der main()-Funktion wurde die Ausgabe der Callback-Funktion verwendet (gelesen und angezeigt), wenn sie benötigt wurde, was zu einem asynchronen Verhalten für das gesamte Schema führte.

Dies ist die Singlethread-Methode, um asynchrones Verhalten der Callback-Funktion mit reinem C . zu erhalten++.

Grundlegende Nutzung der zukünftigen Bibliothek

Die Idee des asynchronen Callback-Funktionsschemas besteht darin, dass die Principal-Funktion zurückkehrt, bevor die Callback-Funktion zurückkehrt. Dies geschah indirekt, effektiv im obigen Code.

Beachten Sie im obigen Code, dass die Callback-Funktion die Haupteingabe für den Code empfängt und die Hauptausgabe für den Code erzeugt. Die C++-Bibliothek, future, hat eine Funktion namens sync(). Das erste Argument dieser Funktion ist die Callback-Funktionsreferenz; das zweite Argument ist die Eingabe für die Callback-Funktion. Die Funktion sync() kehrt zurück, ohne auf den Abschluss der Ausführung der Callback-Funktion zu warten, lässt jedoch zu, dass die Callback-Funktion abgeschlossen wird. Dies bietet asynchrones Verhalten. Während die Callback-Funktion weiter ausgeführt wird, werden die Anweisungen darunter weiter ausgeführt, da die sync()-Funktion bereits zurückgegeben wurde. Dies ist wie ein ideales asynchrones Verhalten.

Das obige Programm wurde im Folgenden unter Berücksichtigung der zukünftigen Bibliothek und ihrer sync()-Funktion neu geschrieben:

#einschließen
#einschließen
#einschließen
Verwenden von Namespace-Std;
Zukunft Ausgabe;
string cb (string stri)

Rücklaufstr;

void PrincipalFn(String-Eingabe)

Ausgabe = async (cb, Eingabe);
cout<<"principal function"<<'\n';

Leere fn()

cout<<"seen"<<'\n';

int main()

string input = string("Rückruffunktion");
PrincipalFn(Eingabe);
fn();
Zeichenfolge ret = Ausgabe.erhalten(); // wartet, bis der Callback zurückkehrt, wenn nötig
cout<0 zurückgeben;

Die Funktion sync() speichert schließlich die Ausgabe der Callback-Funktion in das zukünftige Objekt. Die erwartete Ausgabe kann in der main()-Funktion mit der get()-Memberfunktion des Future-Objekts abgerufen werden.

Fazit

Eine Callback-Funktion ist eine Funktion, die ein Argument, kein Parameter, in einer anderen Funktion ist. Ein Callback-Funktionsschema benötigt eine Principal-Funktion und die Callback-Funktion selbst. Die Deklaration der Callback-Funktion ist Teil der Parameterliste der Principal-Funktion. Die Definition der Callback-Funktion wird im Funktionsaufruf der Principal-Funktion angegeben (in main()). Die Callback-Funktion wird tatsächlich innerhalb der Definition der Principal-Funktion aufgerufen.

Ein Callback-Funktionsschema ist nicht unbedingt asynchron. Um sicherzustellen, dass das Callback-Funktionsschema asynchron ist, machen Sie die Haupteingabe für den Code, die Eingabe für die Callback-Funktion; machen Sie die Hauptausgabe des Codes, die Ausgabe der Rückruffunktion; die Ausgabe der Callback-Funktion in einer Variablen oder Datenstruktur speichern. Führen Sie in der main()-Funktion nach dem Aufrufen der Principal-Funktion andere Anweisungen der Anwendung aus. Wenn die Ausgabe der Callback-Funktion benötigt wird, in der main()-Funktion verwenden (lesen und anzeigen) sie dort und dann.

Kostenlose und Open-Source-Spiele-Engines für die Entwicklung von Linux-Spielen
Dieser Artikel behandelt eine Liste von kostenlosen und Open-Source-Spiele-Engines, die für die Entwicklung von 2D- und 3D-Spielen unter Linux verwend...
Shadow of the Tomb Raider für Linux Tutorial
Shadow of the Tomb Raider ist die zwölfte Erweiterung der Tomb Raider-Reihe – ein Action-Adventure-Franchise von Eidos Montrealdos. Das Spiel wurde vo...
So steigern Sie die FPS unter Linux?
FPS steht für Bilder pro Sekunde. Die Aufgabe von FPS besteht darin, die Bildrate bei Videowiedergaben oder Spielleistungen zu messen. In einfachen Wo...