I'm working with a data provider which offered a C-style API. It expects my data handler function to be provided as a function pointer. I'm trying to encapsulate my end of the logic in a class with the handler being a member function. I'm not sure how to do it. Code snippet below shows my dilemma.
extern "C"
{
/**
* This is part of my data provider's C API (which I cannot change)
* It asks me to put my data handler in a function, then register
* it as a C-style function pointer.
*/
void set_update_callback(void (*p)(struct Data *));
}
/** I tried to encapsulate this data service within a class */
class MyDataClass
{
private:
/** Data should pushed to this queue.
* The queue is created outside my class, then its pointer is passed in from the constructor (below)
*/
queue<DataParsed>* _data_out_queue;
public:
MyDataClass(queue<DataParsed>* data_out_queue): _data_out_queue(data_out_queue) {}
/** Subscribe to the data provider using my handler function */
void subscribe()
{
set_update_callback(handle_data);
}
/**
* This handler function is where the dilemma is:
* - It needs to be static because it needs to be converted to a plain C-style function pointer
* - It needs to be non-static because it needs to write to the member object _data_out_queue
*/
static void handle_data(struct Data *d)
{
// parse data from *d and push into _data_out_queue
}
}
I'm trying to find a clean C++ solution and not putting anything in the global space. Any guidance appreciated!
You can only do this if you have only one instance of MyDataClass e.g.
extern "C"
{
struct Data
{
const char* data;
};
/**
* This is part of my data provider's C API (which I cannot change)
* It asks me to put my data handler in a function, then register
* it as a C-style function pointer.
*/
void set_update_callback(void (*p)(struct Data *));
}
#include <queue>
struct DataParsed
{
int data;
};
/** I tried to encapsulate this data service within a class */
class MyDataClass
{
public:
static MyDataClass& GetInstanceAndSubscribe()
{
static std::queue<DataParsed> data_out_queue;
static MyDataClass instance(data_out_queue);
set_update_callback(handle_data);
return instance;
}
private:
MyDataClass(std::queue<DataParsed>& data_out_queue): _data_out_queue(data_out_queue) {}
/**
* This handler function is where the dilemma is:
* - It needs to be static because it needs to be converted to a plain C-style function pointer
* - It needs to be non-static because it needs to write to the member object _data_out_queue
*/
static void handle_data(struct Data *d)
{
// parse data from *d and push into _data_out_queue
}
/** Data should pushed to this queue.
* The queue is created outside my class, then its pointer is passed in from the constructor (below)
*/
std::queue<DataParsed>& _data_out_queue;
};
int main()
{
auto& my_data_class = MyDataClass::GetInstanceAndSubscribe();
}