使用可变参数模板进行C回调包装

时间:2019-06-09 17:43:48

标签: c++ templates variadic-templates

我目前正在尝试包装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

1 个答案:

答案 0 :(得分:1)

  

但这是否有可能将可变参数传递给std:function?

我不理解您要获取的内容,但是...鉴于args...已固定为该类的模板参数,是的:可以。

在静态方法中进行了两次更正:(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);
 }

但是在我看来,这种解决方案过于复杂。不幸的是,我不明白您想如何使用包装器,因此我不建议您使用更简单的方法。