Reputation: 81
I'm trying to store different callback function addresses in an array. To be able to store function addresses with different signatures, I have defined a union and I use typecasting. This approach seems to work, but it is not very beautiful. Is there a better solution?
typedef union {
void (*callback_s_char)(signed char);
void (*callback_void)(void);
} callback_func_ptr_t;
typedef enum {
EVENT1,
EVENT2,
MAX_EVENTS
} event_t;
callback_func_ptr_t callback_func_ptrs[MAX_EVENTS];
void event_func1(signed char direction) {
printf("success rotated: %d\n", direction);
}
void event_func2(void) {
printf("success button pressed\n");
}
void register_callback(event_t event, void (*ptr)(void)) {
callback_func_ptrs[event].callback_void = ptr;
}
int main(void) {
//register callback functions
register_callback(EVENT1, (void (*)(void))event_func1);
register_callback(EVENT2, (void (*)(void))event_func2);
//call callbacks
if(callback_func_ptrs[EVENT1].callback_s_char != NULL)
(*callback_func_ptrs[EVENT1].callback_s_char)(1);
if(callback_func_ptrs[EVENT2].callback_void != NULL)
(*callback_func_ptrs[EVENT2].callback_void)();
}
Upvotes: 1
Views: 2575
Reputation: 727137
Since you must provide the pointer type implicitly at the point of invocation by specifying the correct field of the union, you might as well do it with a cast. Adding a few typedefs and hiding the cast in a macro could make your code more readable:
typedef void (*callback_s_char_t)(signed char);
typedef void (*callback_void_t)(void);
typedef enum {
EVENT1,
EVENT2,
MAX_EVENTS
} event_t;
callback_void_t callback_func_ptrs[MAX_EVENTS];
void event_func1(signed char direction) {
printf("success rotated: %d\n", direction);
}
void event_func2(void) {
printf("success button pressed\n");
}
void register_callback(event_t event, callback_void_t ptr) {
callback_func_ptrs[event] = ptr;
}
int main(void) {
//register callback functions
REGISTER_CALLBACK(EVENT1, event_func1);
REGISTER_CALLBACK(EVENT2, event_func2);
//call callbacks
if(callback_func_ptrs[EVENT1])
GET_CALLBACK(EVENT1,callback_s_char_t)(1);
if(callback_func_ptrs[EVENT2])
GET_CALLBACK(EVENT2,callback_void_t)();
return 0;
}
Upvotes: 1