user1160713
user1160713

Reputation: 81

C - store different callback function adresses in an array

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

Answers (1)

Sergey Kalinichenko
Sergey Kalinichenko

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;
}

Demo.

Upvotes: 1

Related Questions