为 C 回调包装器使用可变参数模板
Use variadic template for C callback wrapper
我目前正在尝试包装一个 C 库(将其 GTK 命名为训练)。我想看看我是否可以为回调使用可变参数模板,因为它们在信号的回调中具有不同的参数计数。我打算使用 std::function
和可变参数模板。有点像这样:
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;
};
我对此很陌生,但这是否可以将可变参数传递给 std:function
?
but is this even possible to pass the variadic arguments to a std:function?
我不明白你想要获得什么但是...考虑到 args...
被固定为 class 的模板参数,是的:你可以。
在您的静态方法中进行了一些更正:(1) 您必须将 data
转换为 cb_data_t
指针(没有 cb_data
)并且 (2) 您必须考虑到 cbd
是一个指针,所以你必须通过箭头运算符调用 callback()
,而不是通过点运算符
static void callback_from_a_c_function(args... a, void *data)
{ // ......................VV
cb_data_t *cbd = (cb_data_t *)data;
cbd->callback(a...);
} // ^^
或者,也许更好,您可以直接将最后一个参数作为 cb_data_t
指针
传递
static void callback_from_a_c_function(args... a, cb_data_t * cbd)
{ cbd->callback(a...); }
请注意,接收 cd_data_t
指针作为参数,您没有使用 cb_data
成员。
下面是一个完整的编译和简化的例子
#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);
}
但这个解决方案在我看来过于复杂。不幸的是,我不明白你想如何使用你的包装器,所以我不能建议你一些更简单的东西。
我目前正在尝试包装一个 C 库(将其 GTK 命名为训练)。我想看看我是否可以为回调使用可变参数模板,因为它们在信号的回调中具有不同的参数计数。我打算使用 std::function
和可变参数模板。有点像这样:
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;
};
我对此很陌生,但这是否可以将可变参数传递给 std:function
?
but is this even possible to pass the variadic arguments to a std:function?
我不明白你想要获得什么但是...考虑到 args...
被固定为 class 的模板参数,是的:你可以。
在您的静态方法中进行了一些更正:(1) 您必须将 data
转换为 cb_data_t
指针(没有 cb_data
)并且 (2) 您必须考虑到 cbd
是一个指针,所以你必须通过箭头运算符调用 callback()
,而不是通过点运算符
static void callback_from_a_c_function(args... a, void *data)
{ // ......................VV
cb_data_t *cbd = (cb_data_t *)data;
cbd->callback(a...);
} // ^^
或者,也许更好,您可以直接将最后一个参数作为 cb_data_t
指针
static void callback_from_a_c_function(args... a, cb_data_t * cbd)
{ cbd->callback(a...); }
请注意,接收 cd_data_t
指针作为参数,您没有使用 cb_data
成员。
下面是一个完整的编译和简化的例子
#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);
}
但这个解决方案在我看来过于复杂。不幸的是,我不明白你想如何使用你的包装器,所以我不能建议你一些更简单的东西。