C++:将成员函数作为普通函数指针传递的闭包

标签 c++ arduino atmega

我正在尝试调用一个以函数指针作为参数的外部库的成员函数:

Timer::every(unsigned long period, void (*callback)(void));

但不幸的是我要传递的参数是一个成员函数:

void MyClass::the_method_i_want_to_pass(void);

由于我在 Arduino (AVR) 下为 ATMega 编程,所以对 c++11 的支持有限。我的第一种方法引发了类型错误:

void MyClass::the_method_i_want_to_pass() {...}

MyClass::MyClass() {
    // constructor

    Timer *timer = new Timer();
    timer->every(500, [this](){this->the_method_i_want_to_pass();})
}

编译器输出:

warning: warning: lambda expressions only available with -std=c++11 or -std=gnu++11 [enabled by default]

error: no matching function for call to ‘Timer::every(int, MyClass::MyClass()::__lambda0)’

  1. 是否有其他/更好的解决方案?
  2. 关于我当前的方法:(如何)在需要函数指针时可以传递对 lambda 的引用?
  3. 如何确定 Arduino/AVR 是否支持这些 lambda(参见“警告”)?

最佳答案

你的基本问题是你的 Timer 库写得很糟糕:它至少应该使用 void(*)(void*), void*

如果没有 pvoid 或等效项,除了执行代码中的地址之外,您不能传递任何状态以运行过程。作为一个方法也需要一个 this 指针,你真倒霉。

现在,如果您的 MyClass 实例是单例,您可以从其他地方获取 this

否则,您需要创建自己的全局状态,让您可以从特定回调映射到某个状态。如果您的 MyClassTimer 的其他消费者数量有限,您可以拥有一些固定的函数,并让它们全局存储它们的额外状态。

这都是黑客。接下来的事情更糟。

用一些全局状态和一个void()接口(interface)写一个动态库。添加回调时,复制该动态库,在运行时修改其全局状态,将其写出为不同名称的库,加载它,并将纯回调函数传递给您的 Timer 类。

或者通过手动编写机器代码并将页面标记为可执行来在没有库的情况下执行等效操作。

这些都是糟糕的解决方案。这让我想到了一个好方法:找到一个更好的 Timer。如果他们搞砸了这么简单的事情,图书馆的其他部分可能也很糟糕。

关于C++:将成员函数作为普通函数指针传递的闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24352785/

相关文章:

c++ - 上下文信息不足,无法确定类型

c++ - 我正在研究 Arduino Uno。错误 : "' RX' not declared in the scope ."and "duplicate case value"for switch case

c++ - 准确提取 float 的小数部分

c - 连接超声波距离传感器 (HCSR-04) 与 avr ATmega-32?

c - ATMEGA32 熔丝位设置、低熔丝和高熔丝、16MHz、外部晶体?

c++ - 在 std::map 中查找输入数字的最接近范围的最有效标准算法是什么?

c++ - 为什么包含 <utility> 会破坏 GCC 中的结构化绑定(bind)?

c++ - Arduino/C++-使用F()宏将PROGMEM字符串传递给类

c - 使用超声波传感器时距离等于什么公制单位?

c++ - 为什么 boost::dynamic_bitset 是一个模板?