C-Programmierung

Callbacks

Einsatz von Funktionszeigern | | Funktionsprototypen

Nicht immer will man nur ein Endergebnis als Funktionswert zurückliefern, sondern es werden auch Zwischenergebnisse während einer Berechnung benötigt.

Q Wie kann man Zwischenergebnisse zurĂĽckgeben ohne die Funktion zu verlassen?

Dies erreicht man mit einem Zeiger auf eine Funktion, die für jedes Zwischenergebnis aufgerufen wird. Diesen Funktionszeiger nennt man Callback. Man spricht auch häufig von einem Ereignis (Event), welches einen Callback auslöst.

Vorteil: Der Verwendungszweck der Zwischenergebnisse kann beliebig und auch zur Laufzeit verändert werden (Anschauliches Beispiel: MP3-Kompression mit optionaler Fortschrittsanzeige).

Einfaches Beispiel Primzahl-Generierung mit Progress-Callback:

void primes(int a, int b,
            void (*report_callback)(int n))
{
   for (int i=a; i<=b; i++)
      if (is_prime(i))
         report_callback(i);
}

Eine Anwendung wäre die tabellarische Primzahlen-Ausgabe:

void report_callback(int n)
{
   static int counter=0;

   printf("%d ", n);
   if (++counter%10==0) putchar('\n');
}

int main()
{
   primes(1, 1000, report_callback);
   printf("\n");
}

Q Kann man damit mehrere Tabellen ausgeben?

Nein, da der Spaltenzähler counter nur einmalig initialisiert wird.

Die Lösung dafür sind zusätzliche Start- und Stopp-Callbacks:

void primes(int a, int b,
            void (*init_callback)())
            void (*report_callback)(int n))
            void (*exit_callback)())
{
   if (init_callback) init_callback();

   for (int i=a; i<=b; i++)
      if (is_prime(i))
         report_callback(i);

   if (exit_callback) exit_callback();
}

Beispielanwendung:

int counter;

void init_callback()
{
   counter=0;
}

void report_callback(int n)
{
   printf("%d ", n);
   if (++counter%10==0) putchar('\n');
}

void exit_callback()
{
   if (counter%10!=0) putchar('\n');
}

int main()
{
   /* output two prime tables and pause on half-through */
   primes(1, 500, init_callback, report_callback, exit_callback);
   sleep(3);
   primes(501, 1000, init_callback, report_callback, exit_callback);

   /* output one prime tables and pause on half-through */
   primes(1, 500, init_callback, report_callback, NULL);
   sleep(3);
   primes(501, 1000, NULL, report_callback, exit_callback);
}

Callbacks werden insbesondere bei Bibliotheken zur Ăśbermittelung von Zwischenergebnissen oder zur Bekanntmachung von Ereignissen (Events) verwendet.

Einsatz von Funktionszeigern | | Funktionsprototypen

Options: