There is a dangerous way to do this with an instance. It requires disabling a warning/error with -Wno-dangling-pointer
, which indicates the danger.
extern "C" {
void set_update_callback(void (*p)(struct Data*)) //
{}; // function body to test it all compiles
}
class MyDataClass {
private:
void handle_data(struct Data* d) {
}
public:
// Subscribe to the data provider using my handler function
static void subscribe(MyDataClass& my_data_class) {
// set pointer to an instance of self and subscribe to C API
mSelf = &my_data_class;
::set_update_callback(&data_handler_callback);
}
static inline MyDataClass* mSelf{};
static void data_handler_callback(struct Data* d) {
MyDataClass::mSelf->handle_data(d);
}
};
auto main() -> int {
MyDataClass mdc{};
MyDataClass::subscribe(mdc);
return 0;
}
I don't recommend this, but I have used something similar for handling interrupts in a microcontroller system. The other answer using only one instance would be preferred.
Here is another approach using an anonymous namespace to avoid creating global entities. You can only access it in the source file, but MyDataHanler
is outside the namespace, so it can be accessed. (I can see the downvotes now. <shrug.>)
struct MyDataHandler {
void handle_data(struct Data* d);
static inline MyDataHandler* self;
};
namespace {
extern "C" {
void set_update_callback(void (*p)(struct Data*)) //
{ }; // function body to test it all compiles
}
void data_handler_callback(struct Data* d) {
MyDataHandler::self->handle_data(d);
}
void subscribe(MyDataHandler& mdh) {
MyDataHandler::self = &mdh;
::set_update_callback(&data_handler_callback);
}
}
auto main() -> int {
MyDataHandler mdh;
subscribe(mdh);
return 0;
}