{"id":1073,"date":"2025-09-01T08:00:00","date_gmt":"2025-09-01T07:00:00","guid":{"rendered":"https:\/\/jorgeturiel.es\/?p=1073"},"modified":"2025-08-19T16:06:38","modified_gmt":"2025-08-19T15:06:38","slug":"callbacks-en-free-pascal","status":"publish","type":"post","link":"https:\/\/jorgeturiel.es\/?p=1073","title":{"rendered":"CALLBACKS en Free Pascal"},"content":{"rendered":"\n<p>En programaci\u00f3n una CALLBACK (o retrollamada o devoluci\u00f3n en espa\u00f1ol) es un funci\u00f3n ejecutable que se usa como argumento para otra funci\u00f3n, seg\u00fan la <a href=\"https:\/\/es.wikipedia.org\/wiki\/Retrollamada_(inform%C3%A1tica)\">Wikipedia<\/a>.<\/p>\n\n\n\n<p>En unas palabras m\u00e1s sencillas, es tener una funci\u00f3n que en lugar de devolver un valor determinado,<br>lo que hace es llamar a un procedimiento. Este m\u00e9todo de programaci\u00f3n permite crear<br>capas de abstracci\u00f3n. Por ejemplo si los datos retornados por la funci\u00f3n hay que formatearlos<br>o prepararlos de una manera u otra antes de mostrarlos, es m\u00e1s c\u00f3modo hacer esto<br>en un procedimiento espec\u00edfico.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>Vamos a ver como se hace esto en Free Pascal. Empecemos creando un proyecto simple.<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"338\" height=\"416\" src=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2023\/03\/LazarusCrearProyecto.jpg\" alt=\"\" class=\"wp-image-386\" style=\"width:416px;height:auto\" srcset=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2023\/03\/LazarusCrearProyecto.jpg 338w, https:\/\/jorgeturiel.es\/wp-content\/uploads\/2023\/03\/LazarusCrearProyecto-244x300.jpg 244w\" sizes=\"auto, (max-width: 338px) 100vw, 338px\" \/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\"><div class=\"wp-block-image\">\n<figure class=\"alignright size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"563\" height=\"334\" src=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2023\/03\/LazarusEscogerProyecto.jpg\" alt=\"\" class=\"wp-image-388\" srcset=\"https:\/\/jorgeturiel.es\/wp-content\/uploads\/2023\/03\/LazarusEscogerProyecto.jpg 563w, https:\/\/jorgeturiel.es\/wp-content\/uploads\/2023\/03\/LazarusEscogerProyecto-300x178.jpg 300w\" sizes=\"auto, (max-width: 563px) 100vw, 563px\" \/><\/figure>\n<\/div><\/div>\n<\/div>\n\n\n\n<p>Lo primero es declarar como sera el procedimiento que funcionar\u00e1 como CALLBACK. Osea el procedimiento que ser\u00e1 ejecutado cada vez que se produzca una devoluci\u00f3n.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >type\n  TMyCallback = procedure(Const aNumber: integer; var Fin: boolean); <\/pre><\/div>\n\n\n\n<p>El tipo de procedimiento ser\u00e1 <em>TMyCallback<\/em>, y recibir\u00e1 un n\u00famero y una variable <em>booleana<\/em>. La variable booleana, al ser pasada como VAR nos permite cambiar su valor y que este permanezca con ese valor una salga la ejecuci\u00f3n de de la funci\u00f3n, y as\u00ed comunicar al procedimiento que llam\u00f3 al <em>CALLBACK <\/em>que ya no queremos m\u00e1s datos.<\/p>\n\n\n\n<p>Lo siguiente es crear el procedimiento que har\u00e1 uso de las llamadas <em>CALLBACK<\/em>.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >procedure Contar( aCallback: TMyCallback);\n  var\n    i: integer;\n    finalizar: boolean;\n  begin\n    for i := 1 to 10 do\n    begin\n      WriteLn('Contando... ', i);\n      finalizar := False;\n      if Assigned(aCallback) then\n        aCallback(i, finalizar);\n      if finalizar then\n      begin\n        WriteLn('Final');\n        Break;\n      end;\n    end;\n  end;      <\/pre><\/div>\n\n\n\n<p>En este procedimiento contaremos hasta 10, y si la variable finalizar es <em>TRUE<\/em>, paramos de contar. Un detalle a tener en cuenta, es que es posible que la rutina <em>CALLBACK <\/em>no est\u00e9 creada lo que har\u00eda que el programa diera un error en tiempo de ejecuci\u00f3n y se detenga. Para evitar esta situaci\u00f3n, comprobamos que est\u00e9 asignada, con la l\u00ednea:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >if Assigned(aCallback) then\n        aCallback(i, finalizar);<\/pre><\/div>\n\n\n\n<p>Ya solo queda hacer uso del callback. Para ello debemos definir la funci\u00f3n que recibir\u00e1 las llamadas <em>CALLBACK<\/em>.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >  procedure Devolucion(Const Numero: integer; var fin: boolean);\n  begin\n    WriteLn('  -&gt; \u00a1Callback invocado para el numero ', Numero, '!');\n    if Numero = 5 then\n    begin\n      fin := True;\n    end;\n  end;   <\/pre><\/div>\n\n\n\n<p>Puede tener cualquier nombre, pero debe tener los mismo par\u00e1metros que la definici\u00f3n.<br>En ella ponemos un c\u00f3digo sencillo para este ejemplo, en el cual mostramos el n\u00famero recibido y si este es 5, cambiamos el valor de la variable fin para que el procedimiento no continue enviando n\u00fameros.<\/p>\n\n\n\n<p>En la parte principal del programa, escribimos el c\u00f3digo para poner todo esto en marcha.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" > WriteLn('Iniciando el ejemplo de callback con par\u00e1metro...');\n  \/\/ Llama a la funci\u00f3n principal y le pasa 'Devolucion' como el callback.\n{$IFDEF FPC}\n  Contar(@Devolucion);\n{$ELSE}\n  Contar(Devolucion);\n{$ENDIF}\n  WriteLn('Ejemplo de callback finalizado.');\n  ReadLn;  <\/pre><\/div>\n\n\n\n<p>Llamamos al procedimiento <em>Contar<\/em>, pasando como par\u00e1metro el nombre del procedimiento que usar\u00e1 como <em>CALLBACK<\/em>.<br>Para hacer compatible este c\u00f3digo, con <em>Delphi<\/em>, usamos la directiva de compilaci\u00f3n <em>{$IFDEF FPC}<\/em>, ya que en <em>Delphi <\/em>el par\u00e1metro <em>CALLBACK <\/em>no se indica con una <em>@.<\/em><\/p>\n\n\n\n<p>Aqu\u00ed te dejo el c\u00f3digo completo.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:default decode:true \" >program CallbackEjemplo;\n\n  {$mode objfpc}\n  {$H+}\n\n\n  \/\/ Tipo de dato para el callback. Recibe un 'Integer' y devuelve un boleano.\ntype\n  TMyCallback = procedure(const aNumber: integer; var Fin: boolean);\n\n  \/\/ El procedimiento que invoca al callback.\n  \/\/ Ahora, al llamar al callback, le pasamos el valor de la variable 'i'.\n  procedure Contar(aCallback: TMyCallback);\n  var\n    i: integer;\n    finalizar: boolean;\n  begin\n    for i := 1 to 10 do\n    begin\n      WriteLn('Contando... ', i);\n      finalizar := False;\n      if Assigned(aCallback) then\n        aCallback(i, finalizar);\n      if finalizar then\n      begin\n        WriteLn('Final');\n        Break;\n      end;\n    end;\n  end;\n\n  \/\/ La funci\u00f3n que actuar\u00e1 como callback.\n  procedure Devolucion(const Numero: integer; var fin: boolean);\n  begin\n    WriteLn('  -&gt; \u00a1Callback invocado para el numero ', Numero, '!');\n    if Numero = 5 then\n    begin\n      fin := True;\n    end;\n  end;\n\n\nbegin\n  WriteLn('Iniciando el ejemplo de callback con par\u00e1metro...');\n  \/\/ Llama a la funci\u00f3n principal y le pasa 'Devolucion' como el callback.\n{$IFDEF FPC}\n  Contar(@Devolucion);\n{$ELSE}\n  Contar(Devolucion);\n{$ENDIF}\n  WriteLn('Ejemplo de callback finalizado.');\n  ReadLn;\nend.\nend.<\/pre><\/div>\n\n\n\n<p>Saludos<\/p>\n","protected":false},"excerpt":{"rendered":"<p>En programaci\u00f3n una CALLBACK (o retrollamada o devoluci\u00f3n en espa\u00f1ol) es un funci\u00f3n ejecutable que se usa como argumento para otra funci\u00f3n, seg\u00fan la Wikipedia.<\/p>\n","protected":false},"author":2,"featured_media":1072,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[61,27,25],"tags":[64,32,23,21,24],"class_list":["post-1073","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-free-pascal","category-lazarus","category-pascal","tag-ejercicio-programacion","tag-free-pascal","tag-lazarus","tag-pascal","tag-programacion"],"_links":{"self":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/1073","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1073"}],"version-history":[{"count":3,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/1073\/revisions"}],"predecessor-version":[{"id":1076,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/posts\/1073\/revisions\/1076"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=\/wp\/v2\/media\/1072"}],"wp:attachment":[{"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1073"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1073"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jorgeturiel.es\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1073"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}