如何使用C++对象的成员函数作为 C 样式回调?
How to use a C++ object's member function as a C-style callback?
我需要将对象实例函数用作没有参数的 C 样式回调,它不能是静态的,因为我需要访问实例变量并且我无法使用回调修改函数。
调用方函数的签名为:
void attachInterrupt(uint32_t pin, void (*callback)(void), uint32_t mode);
唉,我不能使用捕获列表,因为它是仅限 C 样式的回调,因此以下内容不起作用:
attachInterrupt(pin, [this]() { tracker(); }, mode);
我保留了一个指向对象实例的指针的静态数组,所以我尝试了这个:
static Actuator* actuator;
actuator = instance[index];
attachInterrupt(pin, [] { actuator->tracker(); }, mode);
问题是所有 lambda 函数都共享对存储在执行器中的指针的相同引用,但我需要每个 lambda 函数都使用它存储在 instance[index] 中的特定指针。
我让它正常工作的唯一方法是使用 switch 语句,但我想尽可能避免硬编码。
switch (index) {
case 0:
::attachInterrupt(pin, [] { instance[0]->tracker(); }, mode);
break;
case 1:
::attachInterrupt(pin, [] { instance[1]->tracker(); }, mode);
break;
...
}
必须有一种方法可以在不使用 switch 语句的情况下将数组特定静态元素的引用传递给 lambda 函数,我该如何实现?
如果你知道编译时要注册的回调数量,你可以将回调创建为模板函数:
template <size_t i>
static void callback()
{
instance[i]->tracker();
}
然后,您可以使用std::make_index_sequence
和可变参数模板的解包语法一次性注册:
template <size_t... ids>
void register_all_callbacks_impl(std::index_sequence<ids...>)
{
// the (f(), 0) syntax calls a void function f but returns an int 0
// with this trick you can leverage the unpacking syntax
// to call void functions in an array initialization
int dummy[] = { (attachInterrupt(pin, &callback<ids>, mode), 0)... };
(void)dummy; // omit "unused variable" warnings
}
constexpr size_t COUNT = ...;
void register_all_callbacks()
{
register_all_callbacks_impl(std::make_index_sequence<COUNT>());
}
您现在需要做的就是用大小COUNT
初始化您的instance
数组并调用register_all_callbacks()
。
注意:您需要 C++14 才能make_index_sequence
。
我可能会尝试类似的东西
template<uint32_t pin, uint32_t mode> class callback
{
public:
static void attach() { ::attachInterrupt(pin, &callback::tracker, mode); }
private:
// Make specialization for each combination
static void tracker();
}
然后要注册回调,您将执行以下操作:
callback<5, 3>::attach();
callback<7, 2>::attach();
如果模式是依赖于引脚号的常量,则应使用回调类的静态成员,然后为每个类类型初始化特定值。
const uint32_t callback<7>::mode_for_this_pin = 3; // maybe constexpr instead?
但由于这个问题没有包含太多细节,因此很难给出一个好的解决方案。
我们假设在调用回调时不可能知道引脚,因此由客户端将特定函数关联到每个引脚。
或者,您也可以向类中添加一个static std::function<void()> mfn
成员,然后像这样初始化它:
callback<7, 3>::mfn = [] { your code here };
如果要执行的回调取决于某些条件,这可能很有用。
您的问题没有通用的答案,因为语言不直接支持这一点。最佳解决方案取决于您的问题中未记录的多个因素。
显然,如果特定引脚的功能始终相同,则可以轻松地pin3_callback
或pin3_mode2_callback
功能,并在实现中执行任何适当的操作。
问题中未指定的其他要点何时应进行初始化以及是否需要进行一些清理。
我知道在 Windows 下,过去使用一些汇编代码来生成独特的函数,以应对无法向回调提供用户数据的情况。
- 架构决策:返回std::future还是提供回调
- 正在为Xtensa simcall函数编写回调函数
- 如何在C++中使用非静态成员函数作为回调函数
- FLTK:按下哪个按钮 - 将数字传递给按钮的回调 (lambda)
- 在简单示例中,Python3 + ctypes 回调会导致内存泄漏
- 用于在回调中调用解析器的设计模式
- 如何使用C++对象的成员函数作为 C 样式回调?
- Java从C++回调到C++回调
- 如何将成员函数作为回调参数传递给需要"typedef-ed"自由函数指针的函数?
- 从不同的 cpp 调用回调函数会导致bad_function_call
- pcap_handler回调仅在使用 NPCAP v0.9991 时包含空数据包
- 不带轮询的 SDL2 事件回调
- C++存储带有可变参数的回调
- 如何使用 Node-addon-API 实现 node-nan 回调
- 访问类C++ C 样式回调
- 通过实用程序 fn 将捕获的 lambda 传递给 C 样式回调 - 错误
- C++ 11 - 将 C 样式回调绑定到类成员函数
- 使 C 样式回调对象面向
- 在返回值和"回调"之间做出决定时的样式与一致性
- 如何在对象上获取一个方法,以便将其作为C样式回调传递