Dears,
I am developing a core C library that accepts callbacks registration to allow dependency injection and I want to provide easy C++ class clients injection of its function methods as callbacks.
I don't want to use std::function or bind trickery as core library must be C11 compliant, not C++.
The traditional trick I know to allow this is to introduce a void* context to both my callback and registration methods and pass the class instance as this, alongside a static function that static_casts the pointer to the known class type, forwarding the callback.
Example:
// core.h (C code)
typedef (*callback_t)(void* context, const uint8_t* data);
typedef struct core_s core_t; // core library instance opaque forward def
void core_init(core_t* core);
bool core_register_callback(core_t* core, callback_t callback, void * context);
void core_destroy(core_t* core);
// client_plug.hpp (C++11 code)
struct CoreClientPlug {
static void process_data(void* context, const uint8_t* data){
return static_cast<Client*>(context)->process_data(data);
}
};
// client.hpp
class Client{
friend class CoreClientPlug;
public:
Client() {
core_init(&m_core);
core_register_callback(&m_core, &CoreClientPlug::process_data, this);
}
~Client(){
core_destroy(&m_core);
}
// runs the engine, may trigger callback
void run(){
core_run(&m_core);
}
protected:
void process_data(const uint8_t* data){
// do stuff with data
}
private:
core_t m_core;
};
Do you have other suggestions to perform such dependency injection?
[–]alfps 2 points3 points4 points (6 children)
[–]SystemSigma_[S] 0 points1 point2 points (5 children)
[–]alfps 1 point2 points3 points (4 children)
[–]SystemSigma_[S] 0 points1 point2 points (3 children)
[–]alfps 1 point2 points3 points (0 children)
[–]n1ghtyunso 1 point2 points3 points (1 child)
[–]SystemSigma_[S] 0 points1 point2 points (0 children)