This article needs additional citations for verification. (September 2015) (Learn how and when to remove this template message) |
In computer programming, a callback or callback function is any reference to executable code that is passed as an argument to another piece of code; that code is expected to call back (execute) the callback function as part of its job. This execution may be immediate as in a synchronous callback, or it might happen at a later point in time as in an asynchronous callback. They are also called blocking and non-blocking.
Programming languages support callbacks in different ways, often implementing them with subroutines, lambda expressions, blocks, or function pointers.
There are two types of callbacks, differing in how they control data flow at runtime: blocking callbacks (also known as synchronous callbacks or just callbacks) and deferred callbacks (also known as asynchronous callbacks). While blocking callbacks are invoked before a function returns (as in the C example below), deferred callbacks may be invoked after a function returns. Deferred callbacks are often used in the context of I/O operations or event handling, and are called by interrupts or by a different thread in case of multiple threads. Due to their nature, blocking callbacks can work without interrupts or multiple threads, meaning that blocking callbacks are not commonly used for synchronization or for delegating work to another thread.
Callbacks are used to program applications in windowing systems. In this case, the application supplies (a reference to) a specific custom callback function for the operating system to call, which then calls this application-specific function in response to events like mouse clicks or key presses. A major concern here is the management of privilege and security: while the function is called from the operating system, it should not run with the same privilege as the system. A solution to this problem is using rings of protection.
The form of a callback varies among programming languages:
A customer visited a store, but found the desired item to be out of stock.
They leave their address and a check with a clerk, instructing the clerk to cash in the check and send the item to the address (registering a callback function).
When the item became available, the clerk performs the instruction (calling the callback function).
Callbacks have a wide variety of uses, for example in error signaling: a Unix program might not want to terminate immediately when it receives SIGTERM, so to make sure that its termination is handled properly, it would register the cleanup function as a callback. Callbacks may also be used to control whether a function acts or not: Xlib allows custom predicates to be specified to determine whether a program wishes to handle an event.
The following C code demonstrates the use of callbacks to display two numbers.
#include <stdio.h> #include <stdlib.h> #include <time.h> /* The calling function takes a single callback as a parameter. */ void PrintTwoNumbers(int (*numberSource)(void)) { int val1 = numberSource(); int val2 = numberSource(); printf("%d and %d\n", val1, val2); } /* A possible callback */ int overNineThousand(void) { return (rand()%1000) + 9001; } /* Another possible callback. */ int meaningOfLife(void) { return 42; } /* Here we call PrintTwoNumbers() with three different callbacks. */ int main(void) { time_t t; srand((unsigned)time(&t)); // Init seed for random function PrintTwoNumbers(&rand); PrintTwoNumbers(&overNineThousand); PrintTwoNumbers(&meaningOfLife); return 0; }
Example output:
Template:Random number and Template:Random number Expression error: Unrecognized punctuation character "[". and Expression error: Unrecognized punctuation character "[". 42 and 42
Note how this is different from simply passing the output of the callback function to the calling function, PrintTwoNumbers() - rather than printing the same value twice, the PrintTwoNumbers calls the callback as many times as it requires. This is one of the two main advantages of callbacks.
The other advantage is that the calling function can pass whatever parameters it wishes to the called functions (not shown in the above example). This allows correct information hiding: the code that passes a callback to a calling function does not need to know the parameter values that will be passed to the function. If it only passed the return value, then the parameters would need to be exposed publicly.[example needed]
Another example:
/* * This is a simple C program to demonstrate the usage of callbacks * The callback function is in the same file as the calling code. * The callback function can later be put into external library like * e.g. a shared object to increase flexibility. */ #include <stdio.h> #include <string.h> typedef struct _MyMsg { int appId; char msgbody[32]; } MyMsg; void myfunc(MyMsg *msg) { if (strlen(msg->msgbody) > 0 ) printf("App Id = %d \nMsg = %s \n",msg->appId, msg->msgbody); else printf("App Id = %d \nMsg = No Msg\n",msg->appId); } /* * Prototype declaration */ void (*callback)(MyMsg *); int main(void) { MyMsg msg1; msg1.appId = 100; strcpy(msg1.msgbody, "This is a test\n"); /* * Assign the address of the function "myfunc" to the function * pointer "callback" (may be also written as "callback = &myfunc;") */ callback = myfunc; /* * Call the function (may be also written as "(*callback)(&msg1);") */ callback(&msg1); return 0; }
The output after compilation:
$ gcc cbtest.c $ ./a.out App Id = 100 Msg = This is a test
This information hiding means that callbacks can be used when communicating between processes or threads, or through serialised communications and tabular data.[clarification needed]
In C++, functor is also commonly used beside the usage of function pointer in C.
A simple callback in C#:
public class Class1 { static void Main(string[] args) { Class2 c2 = new Class2(); /* * Calling method on Class2 with callback method as parameter */ c2.Method(CallBackMethod); } /* * The callback method. This method prints the string sent in the callback */ static void CallBackMethod(string str) { Console.WriteLine($"Callback was: {str}"); } } public class Class2 { /* * The method that calls back to the caller. Takes an action (method) as parameter */ public void Method(Action<string> callback) { /* * Calls back to method CallBackMet in Class1 with the message specified */ callback("The message to send back"); } }
A simple callback in Kotlin:
fun main(){ print("Enter text: ") val question = readLine() answer(question, ::meaningOfLife) } fun meaningOfLife(): Int{ return 42 } fun answer(question: String?, answer: () -> Int) { println("Your question: $question") println("Answer: ${answer()}") }
Callbacks are used in the implementation of languages such as JavaScript, including support of JavaScript functions as callbacks through js-ctypes[6] and in components such as addEventListener.[7] However, a native example of a callback can be written without any complex code:
function calculate(num1, num2, callbackFunction) { return callbackFunction(num1, num2); } function calcProduct(num1, num2) { return num1 * num2; } function calcSum(num1, num2) { return num1 + num2; } // alerts 150, the product of 5 and 15 alert(calculate(10, 15, calcProduct)); // alerts 20, the sum of 5 and 15 alert(calculate(5, 15, calcSum));
First a function calculate is defined with a parameter intended for callback: callbackFunction. Then a function that can be used as a callback to calculate is defined, calcProduct. Other functions may be used for callbackFunction, like calcSum. In this example, calculate() is invoked twice, once with calcProduct as a callback and once with calcSum. The functions return the product and sum, respectively, and then the alert will display them to the screen.
In this primitive example, the use of a callback is primarily a demonstration of principle. One could simply call the callbacks as regular functions, calcProduct(num1, num2). Callbacks are generally used when the function needs to perform events before the callback is executed, or when the function does not (or cannot) have meaningful return values to act on, as is the case for Asynchronous JavaScript (based on timers) or XMLHttpRequest requests. Useful examples can be found in JavaScript libraries such as jQuery where the .each() method iterates over an array-like object, the first argument being a callback that is performed on each iteration.
From the JavaScript above, here is how one would implement the same in either REBOL or Red (programming language). Notice the cleaner presentation of data as code.
Red [Title: "Callback example"] calculate: func [ num1 [number!] num2 [number!] callback-function [function!] ][ callback-function num1 num2 ] calc-product: func [ num1 [number!] num2 [number!] ][ num1 * num2 ] calc-sum: func [ num1 [number!] num2 [number!] ][ num1 + num2 ] ; alerts 75, the product of 5 and 15 alert form calculate 5 15 :calc-product ; alerts 20, the sum of 5 and 15 alert form calculate 5 15 :calc-sum
A color tweening example using the Roblox engine that takes an optional .done callback:
wait(1) local DT = wait() function tween_color(object, finish_color, fade_time) local step_r = finish_color.r - object.BackgroundColor3.r local step_g = finish_color.g - object.BackgroundColor3.g local step_b = finish_color.b - object.BackgroundColor3.b local total_steps = 1/(DT*(1/fade_time)) local completed; coroutine.wrap(function() for i = 0, 1, DT*(1 / fade_time) do object.BackgroundColor3 = Color3.new ( object.BackgroundColor3.r + (step_r/total_steps), object.BackgroundColor3.g + (step_g/total_steps), object.BackgroundColor3.b + (step_b/total_steps) ) wait() end if completed then completed() end end)() return { done = function(callback) completed = callback end } end tween_color(some_object, Color3.new(1, 0, 0), 1).done(function() print "Color tweening finished!" end)
A typical use of callbacks in Python (and other languages) is to assign events to UI elements.
Here is a very trivial example of the use of a callback in Python. First define two functions, the callback and the calling code, then pass the callback function into the calling code.
>>> def get_square(val): ... """The callback.""" ... return val ** 2 ... >>> def caller(func, val): ... return func(val) ... >>> caller(get_square, 5) 25
Functions in Julia are first-class citizen, so they can simply be passed to higher-level functions to be used (called) within the body of that functions.
Here the same example above in Julia:
julia> get_square(val) = val^2 # The callback get_square (generic function with 1 method) julia> caller(func,val) = func(val) caller (generic function with 1 method) julia> caller(get_square,5) 25
Original source: https://en.wikipedia.org/wiki/Callback (computer programming).
Read more |