【问题标题】:Binding static member function as callback绑定静态成员函数作为回调
【发布时间】:2017-11-20 12:09:51
【问题描述】:

我正在尝试使用std::bind 将成员函数用作termios.h 标头中sigaction 的回调。我了解成员函数需要特别注意,并已阅读并遵循示例 herehere,但没有这样的运气。

因为我可以通过静态函数,我想如果我让函数保持静态,添加第二个变量作为指向自身的指针(this),我会很好,但没有这样的运气:

// In SerialListener.h
static void callback(int status, SerialListener *ptr);

// In the serial listener constructor

// Set callback
auto cb = std::bind(&SerialListener::callback, std::placeholders::_1, this);
sigAct_.sa_handler = cb;

但是报错如下:

error: cannot convert ‘std::_Bind<void (*std::_Placeholder<1>, SerialListener*))(int, SerialListener*)>’ to ‘__sighandler_t {aka void (*)(int)}’ in assignment sigAct_.sa_handler = cb;

我还尝试了第二个示例中没有静态实现的变体:

// In SerialListener.h
void callback(int status);

// In the serial listener constructor

// Set callback
auto cb = std::bind(&SerialListener::callback, this, std::placeholders::_1);
sigAct_.sa_handler = cb;

产生...

error: cannot convert ‘std::_Bind<std::_Mem_fn<void (SerialListener::*)(int)>(SerialListener*, std::_Placeholder<1>)>’ to ‘__sighandler_t {aka void (*)(int)}’ in assignment sigAct_.sa_handler = cb;

错误看起来很相似,看起来它不能将绑定隐式转换为它需要的处理程序,但是当我从输入类型和返回类型的角度来看它时,它应该可以工作。我错过了什么?

【问题讨论】:

  • @NageG - static 类/结构的成员更像是普通函数:不绑定到特定对象并且不知道 this; this 对待非静态成员。
  • Bind 返回一种闭包object。它不能转换为函数指针。您不能将 __sighandler_t 的另一个参数偷偷带入调用中。
  • sigaction 不是来自signal.h
  • 我也试过在静态函数中使用this和一个void指针,不应该this隐式转换为一个void指针,然后我可以将它转换回SerialListener*?我也试过了,但没有用,但我不明白为什么。
  • 据我所知,没有办法将“用户数据”指针放入信号处理程序,您需要使用从处理程序可见的变量。

标签: c++ c++11 bind


【解决方案1】:

lambda 或bind 都不能帮助您将与信号处理程序签名不匹配的函数设置为信号处理程序。请注意,信号处理函数签名不提供通过不透明指针传递类实例的任何方法。您可以做的最好的事情是在某个静态变量中存储一个指向处理上下文对象的指针:

SerialListener * p_listener;

void On_Signal(int signal_code)
{
    if(p_listener)
    {
         p_listener->DealWith(signal_code); // calling member function
    }
}

p_listener= &my_listener;

sigAct_.sa_handler = &On_Signal;

另请注意,根据信号的性质,信号处理程序中允许的操作范围可能非常有限。

【讨论】:

  • 在上面的示例中,如果我有多个SerialListener 实例,如果p_listerner 指针没有作为参数传递给函数,如何管理它?
  • @NateG 好吧,SerialListener 的多个实例不能同时收听同一个信号。如果它们应该从不同的线程工作,您可以使用线程局部静态变量。如果它们应该处理不同的信号,那么您将需要为每个 SerialListener 编写单独的处理程序,每个处理程序都使用自己的静态变量。
  • 好的,我明白了。棘手的是串行端口特定代码在 SerialListener 类之外,这种方法与我想要的相反。我将一个指向非成员函数的指针传递给 SerialListener 类,然后我希望在该类内部将我的外部回调与该串行端口相关联。看来我的选择有限,我需要稍微修改一下架构。
猜你喜欢
  • 2014-04-14
  • 1970-01-01
  • 2011-01-07
  • 1970-01-01
  • 1970-01-01
  • 2013-08-12
  • 1970-01-01
  • 2013-04-09
  • 1970-01-01
相关资源
最近更新 更多