En programación una CALLBACK (o retrollamada o devolución en español) es un función ejecutable que se usa como argumento para otra función, según la Wikipedia.
En unas palabras más sencillas, es tener una función que en lugar de devolver un valor determinado,
lo que hace es llamar a un procedimiento. Este método de programación permite crear
capas de abstracción. Por ejemplo si los datos retornados por la función hay que formatearlos
o prepararlos de una manera u otra antes de mostrarlos, es más cómodo hacer esto
en un procedimiento específico.
Vamos a ver como se hace esto en Free Pascal. Empecemos creando un proyecto simple.


Lo primero es declarar como sera el procedimiento que funcionará como CALLBACK. Osea el procedimiento que será ejecutado cada vez que se produzca una devolución.
1 2 |
type TMyCallback = procedure(Const aNumber: integer; var Fin: boolean); |
El tipo de procedimiento será TMyCallback, y recibirá un número y una variable booleana. La variable booleana, al ser pasada como VAR nos permite cambiar su valor y que este permanezca con ese valor una salga la ejecución de de la función, y así comunicar al procedimiento que llamó al CALLBACK que ya no queremos más datos.
Lo siguiente es crear el procedimiento que hará uso de las llamadas CALLBACK.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
procedure Contar( aCallback: TMyCallback); var i: integer; finalizar: boolean; begin for i := 1 to 10 do begin WriteLn('Contando... ', i); finalizar := False; if Assigned(aCallback) then aCallback(i, finalizar); if finalizar then begin WriteLn('Final'); Break; end; end; end; |
En este procedimiento contaremos hasta 10, y si la variable finalizar es TRUE, paramos de contar. Un detalle a tener en cuenta, es que es posible que la rutina CALLBACK no esté creada lo que haría que el programa diera un error en tiempo de ejecución y se detenga. Para evitar esta situación, comprobamos que esté asignada, con la línea:
1 2 |
if Assigned(aCallback) then aCallback(i, finalizar); |
Ya solo queda hacer uso del callback. Para ello debemos definir la función que recibirá las llamadas CALLBACK.
1 2 3 4 5 6 7 8 |
procedure Devolucion(Const Numero: integer; var fin: boolean); begin WriteLn(' -> ¡Callback invocado para el numero ', Numero, '!'); if Numero = 5 then begin fin := True; end; end; |
Puede tener cualquier nombre, pero debe tener los mismo parámetros que la definición.
En ella ponemos un código sencillo para este ejemplo, en el cual mostramos el número recibido y si este es 5, cambiamos el valor de la variable fin para que el procedimiento no continue enviando números.
En la parte principal del programa, escribimos el código para poner todo esto en marcha.
1 2 3 4 5 6 7 8 9 |
WriteLn('Iniciando el ejemplo de callback con parámetro...'); // Llama a la función principal y le pasa 'Devolucion' como el callback. {$IFDEF FPC} Contar(@Devolucion); {$ELSE} Contar(Devolucion); {$ENDIF} WriteLn('Ejemplo de callback finalizado.'); ReadLn; |
Llamamos al procedimiento Contar, pasando como parámetro el nombre del procedimiento que usará como CALLBACK.
Para hacer compatible este código, con Delphi, usamos la directiva de compilación {$IFDEF FPC}, ya que en Delphi el parámetro CALLBACK no se indica con una @.
Aquí te dejo el código completo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
program CallbackEjemplo; {$mode objfpc} {$H+} // Tipo de dato para el callback. Recibe un 'Integer' y devuelve un boleano. type TMyCallback = procedure(const aNumber: integer; var Fin: boolean); // El procedimiento que invoca al callback. // Ahora, al llamar al callback, le pasamos el valor de la variable 'i'. procedure Contar(aCallback: TMyCallback); var i: integer; finalizar: boolean; begin for i := 1 to 10 do begin WriteLn('Contando... ', i); finalizar := False; if Assigned(aCallback) then aCallback(i, finalizar); if finalizar then begin WriteLn('Final'); Break; end; end; end; // La función que actuará como callback. procedure Devolucion(const Numero: integer; var fin: boolean); begin WriteLn(' -> ¡Callback invocado para el numero ', Numero, '!'); if Numero = 5 then begin fin := True; end; end; begin WriteLn('Iniciando el ejemplo de callback con parámetro...'); // Llama a la función principal y le pasa 'Devolucion' como el callback. {$IFDEF FPC} Contar(@Devolucion); {$ELSE} Contar(Devolucion); {$ENDIF} WriteLn('Ejemplo de callback finalizado.'); ReadLn; end. end. |
Saludos