I am currently trying to wrap a C library (namele its GTK as training). I wanted to see if I can use variadic templated for the callbacks, as they have varying parameter counts in the callbacks for the signal. I intended to use std::function
and variadic templates. Kind of like this:
template<typename... args> class callback_t { public:
struct cb_data_t
{
std::function<void (args...)> callback;
};
// data contains cb_data
static void callback_from_a_c_function(args... a, void *data)
{
cb_data_t *cbd = (cb_data *)data;
cbd.callback(a...);
}
private:
cb_data_t cb_data;
};
I am pretty new to this, but is this even possible to pass the variadic arguments to a std:function
?
but is this even possible to pass the variadic arguments to a std:function?
I don't understand what you're trying to obtain but... given that the args...
are fixed as template parameter of the class, yes: you can.
With a couple of corrections in your static method: (1) you have to cast data
to a cb_data_t
pointer (no cb_data
) and (2) you have to take in count that cbd
is a pointer so you have to call callback()
through an arrow operator, not through a point operator
static void callback_from_a_c_function(args... a, void *data)
{ // ......................VV
cb_data_t *cbd = (cb_data_t *)data;
cbd->callback(a...);
} // ^^
or, maybe better, you can directly pass the last argument as cb_data_t
pointer
static void callback_from_a_c_function(args... a, cb_data_t * cbd)
{ cbd->callback(a...); }
Note that, receiving the cd_data_t
pointer as argument, you're not using the cb_data
member.
The following is a full compiling, and simplified, example
#include <iostream>
#include <functional>
template <typename ... args>
struct callback_t
{
struct cb_data_t
{ std::function<void (args...)> callback; };
static void callback_from_a_c_function(args... a, cb_data_t * cbd)
{ cbd->callback(a...); }
};
extern "C"
{
void foo (int, long)
{ std::cout << "foo!" << std::endl; }
}
int main ()
{
callback_t<int, long>::cb_data_t cbd{&foo};
callback_t<int, long>::callback_from_a_c_function(0, 1l, &cbd);
}
But this solution seems to me overcomplicated. Unfortunately I don't understand how do you want use your wrapper so I can't suggest you something simpler.