Skip to main content
gamedev.net
🔒 Locked

help with callback functions

Started by Stevieboy 2 replies 700+ views
Original Post
Stevieboy
Stevieboy
Hi, I have benn learning about callback functions recently (for my GUI), but I still don't understand them. As far as I know the definition of a callback function, is a function which has a pointer to another function as a parameter? If I can get this part, then my question is probably more about how they are used, rather than what they are. I just seem to be missing a whole lot?


//The function which will be pointed to
int CalledFunction(int a, void *extradata)//not going to use extra data to 
                                          //keep it simple for post
{
        //do domething.
	return a;
}

//declare pointer to a function.
int (*fpointer)(int a, void *extradata);


//The function which will be doing the calling
void WigCallBack( int Afunctionpointer )//would this take the return value
                                        //of the pointed to function
{

  switch(Afunctionpointer)
    {
		case 1:
                //something
			return 0;

        case 2:
               //something else
			return 0;

	}

}


//Start of main
int _tmain(int argc, _TCHAR* argv[])
{

//assign fpointer which we declared earlier to the function 
fpointer = CalledFunction;


int anInt = 5;

//call the callback function?
WigCallBack((fpointer(anInt, &somedata));


	return 0;
}



Thanks.
Evil Steve
Evil Steve
A function pointer is just as you said - a pointer to a function. Instead of calling a function by name, you can call it via a pointer. It simplifies things a hell of a lot if you use typedef to declare your function pointers. I still can;t write code for function pointers without a typedef.
So, some exampel code. If your call back function takes an int and a void* as in your example, and it returns int, you typedef it like this:
typedef int (*LPCallbackFunction)(int n, void* p);
You can then use the type LPCallbackFunction as you would any other type like int or float. So, if you want to create a function pointer variable that points to your callback function, you'd do this:
// You real function:int CalledFunction(int a, void* p){   return a*2;}// Create a function pointer, and make it point at CalledFunction:LPCallbackFunction pfnCallback; // Create it (just as you'd do "int n;")pfnCallback = CalledFunction;   // Initialize it (just as you'd do "n = 42;") - Notice it's not "pfnCallback = CalledFunction();"// Now we can call the function using the pointer, just as you would call a "real" function, like sopfnCallback(42,NULL);// Or you can do this, it makes no difference whatsoever to the compiler:(*pfnCallback)(42,NULL);

Now, this is the primary reason I find typedefs easier. You can make LPCallbackFunction a parameter to a function. So, if you write a function that you want to call your other function, you can do it like this:
void DoSomething(int a, LPCallbackFunction pfnFunction, int b, void* p){   // Do some random code here   a += b*2 + 16;   // Call the function   pfnFunction(a,p);}// Call DoSomething like this (pass CalledFunction as the function to call)DoSomething(5,CalledFunction,42,NULL);

The great thing is that the function DoSomething doesn't know that pfnFunction really points to CalledFunction. You could have 2 or 3 functions that have the same prototype as CalledFunction but do totally different things. Then you can just pass them off to DoSomething, without modifying how DoSomething works internally.

This is exactly how the window message procedure works in Win32. Windows asks for a pointer to a function to call whenever it gets a message. You don't care how or why windows calls your function, just that it does, and windows doesn't care what your function does. It just gets a pointer to your function, and calls it.
Stevieboy
Stevieboy
Steve, thanks for the reply, thats cleared up a whole lot of things for me.

One of the places I've been looking says to use typedefs as well, now I see what they meant.
It'll probably take me a while to digest it all, but I've got a couple more questions.

When using the callback, as in DoSomething(..), is it the address of pfnFunction which is getting passed (in DoSomethings parameters), or just the return of pfnFunction?

**@ I think I just got it!!!
Using LPCallbackFunction pfnFunction, like that allows you to pass the actual function (its pointer), you are making an actual "type" out of the function where as just trying to use it with out the typedef, you (maybe??) couldn't do that, plus also without the typedef you would have to put the called functions parameters & values there as well? Is that right?

  void DoSomething(int a, LPCallbackFunction pfnFunction, int b, void* p){   // Do some random code here   a += b*2 + 16;   // Call the function   pfnFunction(a,p);}



One other thing, I think you fill out DoSomething as you would simaler to the windows callback function, by this I mean as opposed to normal functions where you would just fill in the parameters?


Thanks again.
Evil Steve
Evil Steve
Quote:
Original post by Stevieboy
When using the callback, as in DoSomething(..), is it the address of pfnFunction which is getting passed (in DoSomethings parameters), or just the return of pfnFunction?
You pass the address of the function to DoSomething(). Similarly you can pass the address of an int or anything else.

Quote:
Original post by Stevieboy
**@ I think I just got it!!!
Using LPCallbackFunction pfnFunction, like that allows you to pass the actual function (its pointer), you are making an actual "type" out of the function where as just trying to use it with out the typedef, you (maybe??) couldn't do that, plus also without the typedef you would have to put the called functions parameters & values there as well? Is that right?
Well, you can do it without a typedef, but the code ends up looking really confusing (As I said, I can't figure out function pointers without a typedef :P). You'd end up with something like this for the DoSomething prototype: void DoSomething(int a, int (*pfnFunction)(int n, void* p), int b, void* p) (I don't know if that's right)


Quote:
Original post by Stevieboy
One other thing, I think you fill out DoSomething as you would simaler to the windows callback function, by this I mean as opposed to normal functions where you would just fill in the parameters?
I don't understand what you're saying here, sorry :)
DoSomething() is just another function, like any other. Its 2nd parameter is a pointer to a function. You fill this part of the parameter in as you would with any other function.

Oh, something that might make things a little easier: In my first source snippet I said that you can also call the function pointer with (*pfnFunction)(42,NULL) - You can also do something similar when you get the address of a function. The following 2 lines are exactly the same:
LPCallbackFunction pfnCallback = CalledFunction; and
LPCallbackFunction pfnCallback = &CalledFunction
The second might be more intuitive, since you can read it as "Take the address of CalledFunction", which fits better with the whole "function pointer" naming. The compiler doesn't care, it generates the same code with or without the ampersand.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.