I'm trying to understand callbacks, and do get the idea, but do not understand why it is really needed.
Specifically, what added benefit does it provide over a normal function call? I'm looking at the accepted answer here : What is a "callback" in C and how are they implemented?
I have redone the same thing below, just without using function pointers. How is that different from this?
void populate_array(int *array, size_t arraySize)
{
for (size_t i=0; i<arraySize; i++)
array[i] = getNextRandomValue();
}
int getNextRandomValue(void)
{
return rand();
}
int main(void)
{
int myarray[10];
populate_array(myarray, 10);
...
}
Is it only beneficial if lower-layer software needs to call a function that was defined at a higher-layer?
This implementation is different in that the only way it knows to populate the array is hard-coded: getNextRandomValue is the way it populates the array, and it is part of the library that provides the populate_array functionality. Essentially, the two functions are baked together into a single whole (the fancy way of saying the same thing is to say that they are "tightly coupled").
With the original implementation I can do all of the things below without changing a line in the populate_array:
int getNextRandomValue(void) {
return rand();
}
int getNextEvenValue(void) {
static int even = 2;
return (even += 2);
}
int getNextNegativeValue(void) {
static int neg = -1;
return neg--;
}
int getNextValueFromUser(void) {
int val;
scanf("%d", &val);
return val;
}
populate_array(myarray, 10, getNextRandomValue);
populate_array(myarray, 10, getNextEvenValue);
populate_array(myarray, 10, getNextNegativeValue);
populate_array(myarray, 10, getNextValueFromUser);
With your implementation I would have to write a separate populate_array for each of these cases. If the way of populating an array that I need is not part of the library, I am on the hook for implementing the whole populate_array, not only its value-producing generator function. This may not be that bad in this case, but in cases where callbacks really shine (threads, asynchronous communications) reimplementing the original without callbacks would be prohibitive.
In your example, getNextRandomValue must be known at compile time. This means that you cannot reuse the function with different definitions of getNextRandomValue, neither let other users link to your code and specify their version of getNextRandomValue. Note that this is not a callback, rather a "generic" function: think of getNextRandomValue as a placeholder for a function.
Callbacks are a special use of "generic" functions: they are called upon completion of an asynchronous task, to notify the user of the operation results (or progress).
I don't think that function pointers only suit low-to-high-level communication. Function pointers, as said, allow you to build generic code in C. A quick example, qsort(): order sorting needs a function that, given a and b, tells whether a>b, a<b or a==b, so that a and b can be placed in the right order. Well, qsort let you provide your own definition for order, thus offering a general, reusable piece of code.
To refine other answers here: Your function populate_array has a bad name. It should be named populate_array_with_random_values.
As said in the answer you linked to "there is no callback in c". There only is a method to pass pointers to function to a function.
Which is useful in general not only for lower-layer software that needs to call a function on a higher-level though this might be often how it is used.
Passing function pointers as parameters is an elegant way to write code. In your example if you want to have two variations on how to get the next random value you already see how it is much easier to pass the function as a parameter rather then trying to pass a parameter that then selects the next function to call using a switch.
Related
I am looking into an callback example in:
https://en.wikipedia.org/wiki/Callback_(computer_programming)
#include <stdio.h>
#include <stdlib.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) {
PrintTwoNumbers(&rand);
PrintTwoNumbers(&overNineThousand);
PrintTwoNumbers(&meaningOfLife);
return 0;
}
I understand all the functions. However, I am wondering except reducing a line, what's the advantage of doing:
PrintTwoNumbers(&overNineThousand);
rather than just using them like regular functions:
int a = overNineThousand();
PrintTwoNumbers(a);
Thanks!
This is a trivial example of what's known as a Higher Order Function.
In this particular example, it isn't very useful. You're right that it would be easier to just pass the data directly.
It's a technique that allows for the generalization of functions though, and is very helpful in reducing code duplication when used properly.
A typical example is the map function that transforms a list:
var arr = [1, 2, 3];
var newArr = arr.map(x => x + 1); // Pass a function that adds one to each element
print(newArr); // Prints [2, 3, 4]
Without higher order functions, you would have to write the same looping code that comprises map every time you want to transform a list. What if I wanted to add 2 to each element somewhere else? Or multiple each by 5? By passing a function, you can tell it how you want it to transform each item, without worrying about the iteration.
As noted in the comments, another example would be sorting functions. They allow you to pass a function that determines sort order. Without that ability, you would need to write a new sorting function for each different sort order and element type.
Sorry I couldn't answer this in C. I understand what's going on in the code you've posted, but I don't know C, so I couldn't give good example code that uses HOFs.
If the question is just computing one element, then yes, a callback is not very useful.
Now if we consider that the function may need to call the callback several times in a (non-)deterministic way, then a callback is required.
Typically, one of the most common callback in C is qsort where the callback is mandatory.
There are at least two situations in which callbacks are useful:
Functions in which a task is performed repeatedly on some data. The example given in the comments is good: a comparison function passed into a sort function as a callback is a good example of a useful callback.
Enumeration functions. This is when you ask a library for a list of objects and you want to act on each one. You would pass a callback to the enumeration function. Example: EnumWindows.
For example:
int f1() {
return 3;
}
void f2(int *num) {
*num = 3;
}
int n1, n2;
n1 = f1();
f2(&n2);
With f1, we can return a value and do "variable=f1()"
But the same can be done with a void function that updates the value of that variable given its address without having to do "variable=f1()".
So, does this mean that we can actually just use void functions for everything? Or is there something that a void function cannot do to replace another int function/(type) function?
The main problem with making everything a void function (which in some people's lexicon is called a "routine") is that you can't chain them easily:
f(g(x))
becomes, if you really want to chain it:
int gout;
f((g(x, &gout), gout))
Which is painful.
Yes you could use void return types for everything and rely exclusively on returning via modified parameters. In fact, you could avoid using functions entirely and put everything in your main method.
As with any other feature of the language, return values give you particular advantages, and its up to you to decide if you want them. Here are some advantages of return values off the top of my head:
Returned values can be assigned to const variables, which can make your code easier to reason about
Certain types of optimisation can be applied by the compiler for returned values (this is more applicable to C++ RVO but may also apply to C's structs; I'm not sure)
Code which uses returned values is often easier to read, especially when the functions are mathematical (e.g. imagine having to declare all the temporaries manually for a large mathematical operation using sin/cos/etc. if they required the output to be via parameters). Compare:
double x = A*sin(a) + B*cos(b);
with
double tmpA, tmpB;
sin(&tmpA, a);
cos(&tmpB, b);
double x = A * tmpA + B * tmpB;
or to use a similar structure as John Zwinck suggested in his answer:
double tmpA, tmpB;
double x = A * (sin(&tmpA, a), tmpA) + B * (cos(&tmpB, b), tmpB);
It is guaranteed that the value will be set no matter what happens inside the function, as this is enforced by the compiler (except some very special cases such as longjumps)
You do not need to worry about checking if the assigned value is used or not; you can return the value and if the requester doesn't need it, they can ignore it (compare this to needing NULL-checks everywhere in your alternative method)
Of course there are also disadvantages:
You only get a single return value, so if your function logically returns multiple types of data (and they can't logically be combined into a single struct), returning via parameters may be better
Large objects may introduce performance penalties due to the need to copy them (which is why RVO was introduced in C++, which makes this much less of an issue)
So, does this mean that we can actually just use void functions for everything?
Indeed. And as it turn out, doing so is a fairly common coding style. But rather than void, such styles usually state that the return value should always be reserved for error codes.
In practice, you usually won't be able to stick to such a style consistently. There are a some special cases where not using the return value becomes inconvenient.
For example when writing callback functions of the kind used by standard C generic functions bsearch or qsort. The expect a callback of the format
int compare (const void *p1, const void *p2);
where the function returns less than zero, more than zero or zero. Design-wise it is important to keep the parameters passed as read-only, you wouldn't want your generic search algorithm to suddenly start modifying the searched contents. So while there is no reason in theory why these kind of functions couldn't be of void return type too, in practice it would make the code uglier and harder to read.
Of course you could; but that does not make it a good idea.
It may not always be convenient or lead to easy to comprehended code. A function returning void cannot be used directly as an operand in an expression. For example while you could write:
if( f1() == 3 )
{
...
}
for f2() you would have to write:
f2( &answer ) ;
if( answer )
{
...
}
Another issue is one of access control - by passing a pointer to the function you are giving that function indirect access to the caller's data, which is fine so long as the function is well behaved and does not overrun. A pointer may refer to a single object or an array of objects - the function taking that pointer has to impose appropriate rules, so it is intrinsically less safe.
Is there a possibility to call function with variable arguments from the C code dynamically?
For example I have text file which contains data (written using this scheme: function_name arguments) for example:
func1 1 2 3
func2 1
func3
My program written in C is parsing this file and looks in a populated array (which holds function name in string and target native function pointer) for function with given name by comparing the string and calls a pointer of this function with arguments from the text file. For example functions like that:
void func1(int a, int b, int c) { }
void func2(int a, int b) { }
void func3() { }
The problem is that even if I know the number of arguments, I don't know how to write in C function pointer call with dynamic number of arguments. Is there a possibility to populate va_list (I know that this is NOT a container or a typical array!) then pass to the native function or any other way to do this? The only way which came into my mind is populating dynarec block with x86 code for calling native function with variable arguments, but it's not a clean solution. Is such thing even possible in plain C?
If it is hard to understand just write and I'll try to explain better. And if you want to write "use va_list" - then read carefully my post once again.
Thanks in advance.
I'm self answering, because this will be a solution for other people. If you want to call functions with variable arguments dynamically without writing direct machine code just use avcall library from FFCALL. Quick reference guide of avcall library can be found here. It's a crossplatform library that makes this possible. For example to call function named func1 with return type void which takes three arguments and all of them are of type int just do this:
#include <avcall.h>
int a = 1, b = 2, c = 3;
av_alist alist;
av_start_void(alist,&func1);
av_int(alist,a);
av_int(alist,b);
av_int(alist,c);
av_call(alist);
You can of course use this for functions which returns value or takes arguments of different type, for more just look at avcall library manual page. :)
I like your way of thinking, because obviously, you are a true hacker, but...
do not try to do it like this.
The proper way of doing this is to go alter these functions so that each one of them accepts an array of int instead of individual int parameters. But I suppose that if you had the freedom to change them, you would have done it already and you would not be asking.
The next best way of doing it is to write a number of functions, conv1(), conv2(), conv3() etc, each accepting an array of int, and a pointer to a function which accepts individual int parameters. So, convN() accepts an array of N integers, and a pointer to a function which accepts N individual int parameters. It reads each int from the array and passes it to the function as a parameter. It can do this, because it has been specifically written to work with a function of precisely that number of parameters. Then, in your table with function names and pointers to functions, add a pointer to the right convN() function, depending on the number of parameters that the target function expects.
Don't hack it.
I am trying to do something interesting(automation) in C. What I want to do is.
Expose an interface to the outer world(developer).
That interface declares some argument based functions.
Will invite developers to implement those functions.
The backend system will calculate some parameters.
Then it will call those implementations by passing the parameters(something like callback).`
It should not be a big deal. But I didn't get any success after going through "think-try" loop so many times. I am getting more and more confused every time.
I am unable to write the code to achieve the functionality. Here is some example code.
Assume I created the below interface.
MyInterface.h
int doSomething(int x, int y);
int doSomethingElseNow(int x, int y);
And asked the developer to include the header file and implement his own definitions for the above specified functions.(some thing like "Interfaces" in Java). Assume he did something like this(might be wrong)
Developer1.c
#include<"MyInterface.h">
int doSomething(int x, int y)
{
return x*y;
}
int doSomethingElseNow(int x, int y)
{
return x+y;
}
Now, my question is how do I call these functions(defined) from some other class. What should be my backend code. This code has to generic. It will be written before developer are asked to define functions. Want to do something like.(is wrong for sure)
Backend.c
#include<"MyInterface.h">
int main()
{
int x, y;
// calculating values of x and y
//calling doSomething
int result = doSomething(x, y);
// doing some calculations on result variable
//calling doSomethingElseNow
int result2 = doSomethingElseNow(x, result);
//do something with result2...
}
Please show me some direction to move on.
You definitely can do this by only declaring and then not implementing your callback functions, as this will force the developer to implement them (if he doesn't, he'll get a linker error). This is what e. g. the SDL library does when it re-#defines the main() function (ugh!)
However, this is not a too wise solution. ("you can" doesn't mean "you should".) Here's why:
On some systems, you won't be able to make a dynamic library out of your code because linkage will fail with undefined symbols.
Only one callback function can be implemented per executable. Sometimes that's insufficient.
The developer can't call his callback function what he wants to call it. This may even introduce name collisions.
It is ugly and conceptually backwards.
So, instead of forcing the implementation of some arbitrarily named functions, make your interfaces expect an explicit pointer to a callback function. This is way more flexible and elegant than your current approach.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What is the point of function pointers?
I am trying to understand where in the practical scenarios function pointers are used.
and also can anyone please give me a practical example where we have to pass function itself as an argument to another function.
Function pointers can be useful when you want to create callback mechanism, and need to pass address of a function to another function.
They can also be useful when you want to store an array of functions, to call dynamically for example.
Callback routines appear to be the most common scenario put forth thus far. However, there are many others ...
Finite State Machines where the elements of (multi-dimensional) arrays indicate the routine that processes/handles the next state. This keeps the definition of the FSM in one place (the array).
Enabling features and disabling of features can be done using function pointers. You may have features that you wish to enable or disable that do similar yet distinct things. Instead of populating and cluttering your code with if-else constructs testing variables, you can code it so that it uses a function pointer, and then you can enable/disable features by changing/assigning the function pointer. If you add new variants, you don't have to track down all your if-else or switch cases (and risk missing one); instead you just update your function pointer to enable the new feature, or disable the old one.
Reducing code clutter I touched upon this in the previous example. Examples such as ...
switch (a) {
case 0:
func0();
break;
case 1:
func1();
break;
case 2:
func2();
break;
case 3:
func3();
break;
default:
funcX();
break;
}
Can be simplified to ...
/* This declaration may be off a little, but I am after the essence of the idea */
void (*funcArray)(void)[] = {func0, func1, func2, func3, funcX};
... appropriate bounds checking on 'a' ...
funcArray[a]();
There are many more. Hope this helps.
One common use is to implement a callback function.
Try to sort something by using qsort library function. It's last parameter is a pointer to the comparator function written by you.
The first thing that comes to my mind as a very useful application is a button. Take the following code:
int buttonID = CreateButton ("Click Me!", 100, 100, 200, 100, onClick);
This would create a button at (100,100) with width 200 and height 100. Every time you click it, onClick is called.
I use something similar in a personal Windows API wrapper. It makes creating buttons etc so much easier.
There are two major uses for function pointers:
callbacks - used for event handlers, parser specialization, comparator function passing...
plugins and extensions - the pointers to functions provided by plugins or library extensions are gatherd by a standard functio GetProcAddress, dlsym or similar, which take the function identifier as name and return a function pointer. Absolutely vital for APIs like OpenGL.
Well, the #1 stock answer is: qsort. The comparator routine that qsort will use is passed as a function pointer. A lot of other “generic algorithm” functions will take comparators in similar ways; e.g. perhaps a hashtable implementation might accept your hash function.
C-language GUI toolkits and application frameworks (e.g. Gnome/Gtk+/Glib) often accept function pointers as “callbacks” for timer or user interface events. (EG: “call this function whenever this button is clicked” or “…whenever this timer expires”)
In fact, most “OOP-like” or “event-driven” code in C will accept function pointers for a similar reason.
You can use it to pass a callback to a function. For instance, you might want to sort an array using qsort(). This function takes a comparison function as one of its arguments, which means that you can use your own sorting orders:
// All odd numbers are before even numbers
int cmpoddeven(const void *xp, const void *yp) {
int x = *((int*) xp);
int y = *((int*) yp);
if(x == y)
return 0;
if(x % 2 == y % 2) {
return (x < y ? -1 : 1);
if(x % 2 == 1)
return -1;
return 1;
}
int main() {
int array[] = {1, 2, 3, 4, 5};
// calling qsort with cmpoddeven as the comparison function
qsort(array, 5, sizeof(int), &cmpoddeven);
// array == {1, 3, 5, 2, 4};
}
In MOST cases, it's essentially the C way of doing dependency inversion. The wiki article states:
A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend upon details. Details should depend upon abstractions.
The classic example ofqsort does this in the sense that the higher-level sort function does not depend on the type, size, or comparison method of the data to be sorted. So if you qsort() an array of ints, the details are sizeof(int) and your compare implementation. The abstraction is an array of arbitrarily sized elements and a function that compares elements of that type.
See also: Inversion of Control.
I'm surprised no one has mentioned pthread_create() as an example.
The only common use I can think of that cannot be generalized as dependency inversion is implementing switch-like flow control on non-switchable data types. For example, if you've ever wanted to switch on a string, create arrays mapping sorted string keys to function pointers and do a binary search. It's not O(1) like a switch, but better than blindly doing strcmp()'s in a big if-else until you find a match. But maybe not any better than tokenizing the string and using an actual switch.