Pointers to Functions in C
/I’m re-writing my neopixel animation software for the new light. I’m using a C feature that is sometimes very useful. I’m using pointers to functions.
Note that this is quite strong magic. If you don’t use it properly your program will just stop with no errors or warnings. But then again, that’s pretty much how it is when you write Arduino code anyway, so feel free to have a go. You won’t break any hardware.
The reason why I’m using function pointers is that I want to make the program to select between different animations to control the lights. The update behaviour for each animation is a different function. For example, I’ve got two different displays, one which walks colours around the lights and one which just displays the text in a particular colour. That means I’ve got two update functions:
void update_coloured_message()
{
// update the coloured message
}
void update_text_message()
{
// update the text message
}
Each of these is a function that accepts no parameters and does not return a result. I can create a C variable that can refer to these methods as follows
void (*animation_update) ();
This rather convoluted syntax creates a variable called animation_update that can refer to methods that accept no parameters and don’t return a value. I can make this variable refer to one of my update methods by using a simple assignment:
animation_update = update_text_message;
Note that normally when you want to create a reference to a value in C or C++ you need to put an ampersand (&) in front of the thing you are getting a pointer to. In the case of function references you can leave this out. This is either a neat trick to make C programming easier or a nasty trick to make C programming more confusing. I’ll let you decide.
Anyhoo, once I’ve set animation_update to refer to a function I can call the pointer just as I would the function:
animation_update();
I’ve actually gone one more, in that I’m using function pointers in a structure. Go me. I’ve got a structure that describes an animation in terms of the function that sets up the animation, the function that updates the animation and the number of frames it should run for:
struct Animation_item
{
void(*animation_setup) ();
void(*animation_update)();
int duration;
};
I then create an array of these items that contain all the animations that I want to move between:
struct Animation_item animations[] = {
{ setup_coloured_message, update_coloured_message, 600 },
{setup_walking_colours, update_walking_colours, 600} };
Then just need to count around the array to move between animations.
animations[animation_number].animation_update();
This statement calls the animation update method for the animation that is selected by the value in animation_number. If I add more animations to the array my program just picks them up automatically with no need to change anything else.