C++ - 如何在不静态的情况下将回调绑定到类方法?
C++ - How to bind a callback to a class method without being static?
我有我的类:
class Foo
{
public:
(...)
private:
void mycallback(void* buff, wifi_promiscuous_pkt_type_t type);
void registerMyCallback();
};
mycallback
是回调。
我想使用esp_wifi_set_promiscuous_rx_cb
方法来注册mycallback
,以便在检测到WiFi数据包时,将执行此回调方法。
esp_wifi_set_promiscuous_rx_cb
签名为:
esp_err_t esp_wifi_set_promiscuous_rx_cb(wifi_promiscuous_cb_t cb);
其中wifi_promiscuous_cb_t
定义是:
typedef void (* wifi_promiscuous_cb_t)(void *buf, wifi_promiscuous_pkt_type_t type);
我想在我的类中使用mycallback
方法,因此我根本不能这样使用:
void Foo::registerMyCallback()
{
esp_wifi_set_promiscuous_rx_cb(&mycallback);
}
我知道如果我只是让我的方法成为静态的,我可以使用类似的东西。 无论如何,我可以在不进行回调static
的情况下将mycallback
绑定到esp_wifi_set_promiscuous_rx_cb
吗?
我尝试了以下方法:
esp_wifi_set_promiscuous_rx_cb(std::bind(&Foo::mycallback, this, std::placeholders::_1, std::placeholders::_2));
但是我仍然遇到以下错误:
cannot convert 'std::_Bind_helper<false, void (Foo::Foo::*)(void*, wifi_promiscuous_pkt_type_t),
Foo::Foo*, const std::_Placeholder<1>&, const std::_Placeholder<2>&>::type
to
'wifi_promiscuous_cb_t {aka void (*)(void*, wifi_promiscuous_pkt_type_t)}' for argument '1'
您使用的库是C包。
因此,唯一有保证的传递有效函数的方法是传递带有 C 链接的 C 函数。然后,此函数可以在对象上调用该方法。
如果希望回调方法是非静态的,则需要将指向回调对象的指针(ore引用(存储在回调函数可以找到它的位置。(在大多数 C 回调函数中,您可以提供一个传递给回调的 void* 对象,但此接口似乎不允许这样做,因此您必须自己保存值(。
Foo* myCBObject = nullptr;
extern "C" void myCB(void *buf, wifi_promiscuous_pkt_type_t type)
{
try
{
myCBObject->mycallback(buff, type);
}
catch(...) {} // Don't allow exceptions to cross C linkage
}
...
// Your code.
void Foo::registerMyCallback()
{
myCBObject = this;
esp_wifi_set_promiscuous_rx_cb(myCB);
}
注意:不应将静态成员函数注册到 C 库。如果这有效,那只是偶然的。不能保证静态函数具有与 C 函数相同的调用约定(它们通常这样做,但不能保证(。
经过一些研究,我希望我找到了解决方案。诀窍是先绑定成员函数,然后从 std::function 获取函数指针。请注意my_wifi_promiscuous_cb_t
和std::function::target<>()
的用法。
#include <iostream>
#include <functional>
using namespace std::placeholders;
// using fake definitions
extern "C"
{
enum wifi_promiscuous_pkt_type_t {};
typedef int32_t esp_err_t;
typedef void (*wifi_promiscuous_cb_t)(void* buf, wifi_promiscuous_pkt_type_t type);
typedef void my_wifi_promiscuous_cb_t(void* buf, wifi_promiscuous_pkt_type_t type);
esp_err_t esp_wifi_set_promiscuous_rx_cb(wifi_promiscuous_cb_t cb)
{
return 0;
}
}
class Class
{
public:
void mycallback(void* buff, wifi_promiscuous_pkt_type_t type) {}
void registerMyCallback() {
std::function<void(void*, wifi_promiscuous_pkt_type_t)> fun2 = std::bind(&Class::mycallback, this, _1, _2);
esp_wifi_set_promiscuous_rx_cb(fun2.target<my_wifi_promiscuous_cb_t>());
}
};
int main()
{
Class c;
c.registerMyCallback();
}
相关文章:
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 架构决策:返回std::future还是提供回调
- 在基于范围的for循环中使用结构化绑定声明
- 使用 LuaBridge 将 LuaJIT 绑定到C++会导致"PANIC: unprotected error"
- C++ - 如何在不静态的情况下将回调绑定到类方法?
- ROS 订阅回调 - 使用 boost::绑定成员函数
- 将非静态函数绑定到回调时出现问题
- C++绑定回调到类
- 我应该始终使用"T&&"而不是"const T&"或"T&"来绑定到回调函数吗?
- 将静态成员函数绑定为回调
- boost ::绑定发送变量的回调args到回调函数
- ROS:将回调函数和对象成员绑定到订阅节点
- boost::使用成员函数绑定回调的帮助
- 将回调绑定到到期的共享_ptr
- C++ 11 - 将 C 样式回调绑定到类成员函数
- 是否可以将 bind() *this 绑定到类成员函数以回调 C API
- 当通知程序/信号超出范围时,在提升绑定中解除分配回调侦听器对象
- 用API模拟“std::shared_ptr”的智能指针,将回调绑定到refcount-modifying事件,例如re
- 在构造函数中绑定到类中的回调方法
- Boost绑定回调函数指针作为参数