反馈CPP成员到C回调包装器

时间:2018-04-04 12:09:23

标签: c++ c callback member

我一直在使用带有C ++回调的C库。例如,我有以下方法:

int button(int iconid, const char *label, UIhandler handler);

我可以用作:

button(ICON_COLOR, "Some text", callback);

我现在想要使用C ++成员,但我不能按原样传递它的指针。因此,我有以下基于SO的发现和阅读其他实现的包装代码:

template <typename T>
struct Callback;

template <typename Ret, typename... Params>
struct Callback<Ret(Params...)> {
    template <typename... Args>
    static Ret callback(Args... args) { return func(args...); }
    static std::function<Ret(Params...)> func;
};

// Initialize the static member.
template <typename Ret, typename... Params>
std::function<Ret(Params...)> Callback<Ret(Params...)>::func;

template <class InstanceClass>
UIhandler ofxBluiCptr(InstanceClass  * instance, void (InstanceClass::*instanceMethod)(int, UIevent))
{
    Callback<void(int, UIevent)>::func = std::bind( instanceMethod, instance, std::placeholders::_1, std::placeholders::_2 );
    void (*c_func)(int, UIevent) = static_cast<decltype(c_func)>(Callback<void(int, UIevent)>::callback);
    return c_func;
}

我现在可以按如下方式使用C库:

button(ICON_COLOR, "Some text", ofxBluiCptr(this, &ofApp::buttonPressed ))

但是我很难理解。任何人都可以提供这方面的反馈,也许可以评论这种方式是否安全?

1 个答案:

答案 0 :(得分:1)

如果我理解正确,你想传递成员函数,为此你需要“绑定”它this

有两种简单的方法可以做到这一点。如果你可以得到this指针,只需创建一个静态包装函数,它将调用该成员,使用这个this指针。

在更有可能无法执行此操作的事件中,创建一个将捕获this的lambda,并接受您要传递给CB的参数。使用这个lambda作为你的CB。

auto myCB = [this](auto & param1) { this->member(param1);}

BTW,无论何时看到bind,都要检查是否使用lambdas创建更简单的代码。在大多数情况下,你会。

这有一个缺点就是它不能用于那里的C风格函数指针。

要解决此问题,您可以使用相关实例包装每个CB。例如:

struct Wrapper{
  static CB_instance* instance;
  static void myCallback(Param1 p1, Param2 p2) {
      instance->callback(p1, p2);
}

现在,Wrapper::myCallback可以用作C函数指针。 如果您将它变为寺庙,您将获得代码,与您开始使用的代码非常相似......