调整 lambda 语法以匹配所需的签名

问题描述 投票:0回答:1

我找到了this问题,但答案似乎不符合我的要求。 答案建议使用

static
函数,而不是我需要访问类成员。

我的(不工作的)理想代码是:

在 myclass.h 中:

private:
    int foo = 0;

    hw_timer_t *_timer1s;
    void Setup();

在 myclass.cpp 中:

void MyClass::Setup()
{
    _timer1s = timerBegin(0, 80, true);
    timerAttachInterrupt(_timer1s, [this]()
    {
        foo++;
    }, true);
}

当然我得到了已知的转换错误:

不存在从“lambda ->void”到“void (*)()”的合适转换函数

我理解链接问题的解释,但我不明白如何更改建议的代码以捕获/访问类成员(即

foo
)。使用
static
函数不允许我这样做。

这里正确的语法是什么?

更新

根据要求,我添加了整个班级代码:

我的班级.h

#ifndef MYCLASS_H
#define MYCLASS_H

#include <Arduino.h>
#include <RTClib.h>

class MyClass
{
public:
    MyClass();

private:
    int foo = 0;

    hw_timer_t *_timer1s;
    void Setup();
};

#endif // MYCLASS_H

myclass.cpp:

#include "myclass.h"

MyClass::MyClass()
{
    Setup();
}

void MyClass::Setup()
{
    _timer1s = timerBegin(0, 80, true);
    timerAttachInterrupt(_timer1s, [this]()
    {
        foo++;
    }, true);
    timerAlarmWrite(_timer1s, 1000000, true);
    timerAlarmEnable(_timer1s);
}

这里编译输出错误:

src/myclass.cpp: In member function 'void MyClass::Setup()':
src/myclass.cpp:40:12: error: cannot convert 'MyClass::Setup()::<lambda(void*)>' to 'void (*)()'
     }, true);

In file included from /home/mark/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp32-hal.h:92,
                 from /home/mark/.platformio/packages/framework-arduinoespressif32/cores/esp32/Arduino.h:36,
                 from include/myclass.h:4,
                 from src/myclass.cpp:1:
/home/mark/.platformio/packages/framework-arduinoespressif32/cores/esp32/esp32-hal-timer.h:40:53: note:   initializing argument 2 of 'void timerAttachInterrupt(hw_timer_t*, void (*)(), bool)'
 void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge);

Visual Studio Code 的内联助手报告:

不存在从“lambda ->void”到“void (*)()”的合适转换函数

lambda arduino static esp32 arduino-c++
1个回答
0
投票

捕获 lambda 与您需要提供给

void(*)()
timerAttachInterrupt
不匹配。解决方案是使用
timerAttachInterruptArg
代替并提供
this
作为参数:

void MyClass::Setup()
{
    _timer1s = timerBegin(0, 80, true);
    timerAttachInterruptArg(_timer1s, [](void* instance)
    {
        // cast `instance` back to a `MyClass*`:
        auto This = static_cast<MyClass*>(instance);
        This->foo++;
    }, this);
//     ^^^^   this becomes `void* instance` in the lambda
    //...
}

当然,如果

foo
是私有的,这将不起作用。您可以调用
static
成员函数而不是 lambda 来解决这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.