c++ - arduino (esp8266/esp32) 股票回调类成员函数

标签 c++ arduino

有人可以帮我写下面的代码吗?
我有一个自定义类,我想为 ticker 函数 onTickerCallback() 定义一个回调。
它在 ESP8266 上编译和运行,但在 ESP32 上不编译和运行。
我看到 ESP32 Ticker::once 有不同的声明,但我的 C++ 知识无法帮助我找到解决方案。

测试.h

class Test {
  public:
    void start();
    void doSomething();
  private:
    void onTickerCallback();
};

测试.cpp

#include <Arduino.h>
#include <Test.h>
#include <functional>

// for ESP8266: https://github.com/esp8266/Arduino/blob/master/libraries/Ticker/src/Ticker.h
// for ESP32:   https://github.com/espressif/arduino-esp32/blob/master/libraries/Ticker/src/Ticker.h
#include <Ticker.h>

Ticker ticker;

void Test::start(){
  ticker.once(5, std::bind(&Test::onTickerCallback, this) );
}

void Test::onTickerCallback() {
  doSomething();
}

void Test::doSomething() {
  Serial.println("Hello");
}

main.cpp

#include <Arduino.h>
#include <Test.h>

Test t;

void setup() {
  Serial.begin(115200);
  t.start();
}

void loop() {
}

在 ESP32 上我得到以下错误:

error: no matching function for call to 'Ticker::once(int, std::_Bind_helper<false, void (Test::*)(), Test*>::type)'  
note: candidate: void Ticker::once(float, Ticker::callback_t)
   void once(float seconds, callback_t callback)  
note:   no known conversion for argument 2 from 'std::_Bind_helper<false, void (Test::*)(), Test*>::type {aka std::_Bind<std::_Mem_fn<void (Test::*)()>(Test*)>}' to 'Ticker::callback_t {aka 
void (*)()}'  
note: candidate: template<class TArg> void Ticker::once(float, void (*)(TArg), TArg)
   void once(float seconds, void (*callback)(TArg), TArg arg)  
note:   mismatched types 'void (*)(TArg)' and 'std::_Bind<std::_Mem_fn<void (Test::*)()>(Test*)>'  

最佳答案

这两个 Ticker.h 文件的实现有点不同。在 ESP8266 上,once 方法需要类型“callback_function_t”,其中 callback_function_t 定义为:

typedef std::function<void(void)> callback_function_t;

在 ESP32 上,它期望类型“callback_t”定义为:

typedef void (*callback_t)(void);

在您的代码示例中,std::bind 提供了预期的 std::function 类型。 ESP32 Ticker.h 不是这种情况,它需要一个函数指针。您有两个选择:

  1. 不要将 onTickerCallback 函数作为测试类的一部分,只需为回调创建一个自由函数即可。 (请注意,只有当回调不需要成为测试类的一部分时,这才是可接受的)。
#include <Arduino.h>
#include <Test.h>
#include <functional>

// for ESP8266: https://github.com/esp8266/Arduino/blob/master/libraries/Ticker/src/Ticker.h
// for ESP32:   https://github.com/espressif/arduino-esp32/blob/master/libraries/Ticker/src/Ticker.h
#include <Ticker.h>

Ticker ticker;

void callbackFunction() {
  Serial.println("Hello");
}

void Test::start(){
  ticker.once(5, callbackFunction);
}
  1. 创建一个接受测试实例的免费函数,并使用它来调用您的函数。 (请注意,这还需要公开 onTickerCallback,我想不出解决这个问题的真正方法)。
#include <Arduino.h>
#include <Test.h>
#include <functional>

// for ESP8266: https://github.com/esp8266/Arduino/blob/master/libraries/Ticker/src/Ticker.h
// for ESP32:   https://github.com/espressif/arduino-esp32/blob/master/libraries/Ticker/src/Ticker.h
#include <Ticker.h>

Ticker ticker;

void callbackFunc(Test* testInstance) {
  testInstance->onTickerCallback();
}

void Test::start(){
  ticker.once(5, callbackFunc, this);
}

void Test::onTickerCallback() {
  doSomething();
}

void Test::doSomething() {
  Serial.println("Hello");
}

奖励:考虑一下后,您可以使用 lambda 而不是创建函数(请注意,您需要在 lambda 之前有一个 + 号才能使其用作函数指针)。这看起来像:

#include <Arduino.h>
#include <Test.h>
#include <functional>

// for ESP8266: https://github.com/esp8266/Arduino/blob/master/libraries/Ticker/src/Ticker.h
// for ESP32:   https://github.com/espressif/arduino-esp32/blob/master/libraries/Ticker/src/Ticker.h
#include <Ticker.h>

Ticker ticker;

void Test::start(){
  ticker.once(5, +[](Test* testInstance) { testInstance->onTickerCallback(); }, this);
}

void Test::onTickerCallback() {
  doSomething();
}

void Test::doSomething() {
  Serial.println("Hello");
}

关于c++ - arduino (esp8266/esp32) 股票回调类成员函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60985496/

相关文章:

c++ - LCOV 在函数末尾分支

c++ - 声明一个内部有结构数组的结构数组

c++ - 在构造函数调用期间将 this 传递给对象内的对象

c++ - "DHT11 ? 0 : -40;"这个语法是什么意思,它叫什么?

c++ - Pontech & 步进电机

audio - Arduino AnalogRead每隔两个样本返回0

c++ - 在 C++ 中索引整数指针

C++ 可变关键字如何影响容器的性能?

python - 定义引脚时出现 InvalidPinDefError

arduino - 将多个 BLE 设备连接到 Arduino