C - 在数组中存储不同的回调函数地址

时间:2018-01-31 14:34:05

标签: c callback function-pointers unions

我正在尝试在数组中存储不同的回调函数地址。为了能够存储具有不同签名的函数地址,我已经定义了一个union,我使用了类型转换。这种方法似乎有效,但它不是很漂亮。有更好的解决方案吗?

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

1 个答案:

答案 0 :(得分:0)

由于您必须通过指定union的正确字段隐式地在调用点提供指针类型,因此您也可以使用强制转换来执行此操作。添加一些typedef并将转换隐藏在宏中可以使代码更具可读性:

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.