Converting a compile-time C callbacks to compile-time C++ callbacks

184 Views Asked by At

I'm converting a C codebase to C++ for an embedded device (ESP32). One thing that's repeating in the current code is a way of declaring "callbacks" to C modules and implement them in the "user" module.

For example, the current API for a Button module is the following:

void btn_init(uint32_t gpio);

// callbacks
extern bool btn_on_change_isr(bool is_pressed, uint32_t timer_duration_s);
extern bool btn_on_timer_isr(uint32_t duration_s);

Knowing that functions are externed by default, this is simply a mark that the module is not the one responsible to implement them. The main advantage of this method is that unimplemented callbacks are catched at compile time by the linker.

While transitioning to C++, I'd like to keep that compile-time check for existance of callback implementation (I don't need dynamic dispatch), but also allow creating multiple objects, so I need classes.

While I'm new to CRTP & Policy-based-design, I guess I should go with one of these. Or maybe template functors? What is the difference between these two?

My current idea is the following:

template <typename Impl>
class Button
{
  public:
    Button(uint32_t gpio, Impl impl_ = Impl())
        : impl(impl_)
    {
        (void)gpio;
    }
    bool on_change_isr(bool is_pressed, uint32_t timer_duration_s)
    {
        return impl.on_change_isr(is_pressed, timer_duration_s);
    }
    bool on_timer_isr(uint32_t duration_s)
    {
        return impl.on_timer_isr(duration_s);
    }

  private:
    Impl impl;
};

Where the implementing code is:

class MyButton
{
public:
    bool on_change_isr(bool is_pressed, uint32_t timer_duration_s)
    {
       // implementation 
    }
    bool on_timer_isr(uint32_t duration_s)
    {
       // implementation 
    }
};

One main thing that bugs me here is that I'd still like to keep the implementation in a cpp file rather then the header. For the Button class, I'd like to implement the constructor in a cpp file. How can I achieve that?

Overall, does this makes sense? Is there a better way to injecting callbacks without using inheritance?

0

There are 0 best solutions below