Using Function Pointers for Callbacks in C++

You plan to call some function func1, and at runtime you need it to invoke another function func2. For one reason or another, however, you cannot simply hardcode the name of func2 within func1. func2 may not be known definitively at compile time, or perhaps func1 belongs to a third-party API that you can’t change and recompile. In either case, you need a callback function.

In a situation such as that shown in below code, a function pointer is a good idea if updateProgress and longOperation shouldn’t knowanything about each other. For example, a function that updates the progress by displaying it to the user—either in a user interface (UI) dialog box, in a console window, or somewhere else—does not care about the context in which it is invoked. Similarly, the longOperation function may be part of some data loading API that doesn’t care whether it’s invoked from a graphical UI, a console window, or by a background process.

The first thing you will want to do is determine what the signature of the function is you plan to call and create a typedef for it. typedef is your friend when it comes to function pointers, because their syntax is ugly. Consider howyou would declare a function pointer variable f that contains the address of a function that takes a single integer argument and returns a boolean. It would look like this:
bool (*f)(int); // f is the variable name
One could argue, convincingly, that this is no big deal and that I’m just a whiner. But what if you want a vector of such function pointers?
vector<bool (*)(int)> vf;
Or an array of them?
bool (*af[10])(int);
Function pointers do not look like ordinary C++ variable declarations whose format is often a (qualified) type name followed by a variable name. This is why they can make for messy reading.
Thus, in below code, I used a typedef like this:
typedef bool (*FuncPtrBoolInt)(int);

Once that was out of the way, I was free to declare function pointers that have the signature of returning bool and accepting a single integer argument as I would any other sort of parameter, like so:

void longOperation(FuncPtrBoolInt f) {
// …
Now, all longOperation needs to do is call f like it would any function:
f (l/1000000);
In this way, f can be any function that accepts an integer argument and returns bool. Consider a caller of longOperation that doesn’t care about the progress. It can pass in a function pointer of a no-op function:
bool whoCares(int i) {return(true);}
//…
longOperation(whoCares);
More importantly, which function to pass to longOperation can be determined dynamically at runtime.


#include <iostream>
// An example of a callback function
bool updateProgress(int pct)

{
std::cout << pct << "% complete...\n";
return(true);
}

// A typedef to make for easier reading
typedef bool (*FuncPtrBoolInt)(int);
// A function that runs for a while
void longOperation(FuncPtrBoolInt f)

{
for (long l = 0; l < 100000000; l++)
if (l % 10000000 == 0)
f(l / 1000000);
}
int main( )

{
longOperation(updateProgress); // ok
}

 

Advertisements

About Khuram Ali

Programming... Programming and Programming...!!!

Posted on June 21, 2013, in C++ and tagged , , , , , , , , . Bookmark the permalink. 1 Comment.

  1. good job and it is twetted now on my twitter 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: