为 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);
 }

但这个解决方案在我看来过于复杂。不幸的是,我不明白你想如何使用你的包装器,所以我不能建议你一些更简单的东西。