提问人:Mark 提问时间:11/14/2023 最后编辑:Mark 更新时间:11/16/2023 访问量:47
调整 lambda 语法以匹配所需的签名
Adjust lambda syntax to match required signature
问:
我找到了这个问题,但答案似乎不符合我的要求。
答案建议使用函数,而是我需要访问类成员。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
这里的正确语法是什么?
更新
根据要求,我添加了整个类代码:
我的class.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
我的类.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 (*)()”的合适转换函数
答:
1赞
Ted Lyngmo
11/15/2023
#1
捕获 lambda 将与您需要提供给 的 lambda 不匹配。解决方案是改用 timerAttachInterruptArg
并作为参数提供。void(*)()
timerAttachInterrupt
this
void timerAttachInterruptArg(hw_timer_t * timer, void (*userFunc)(void*), void * arg);
timer
- 计时器结构。userFunc
- 触发中断时调用的功能。arg
- 指向中断参数的指针。
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
例:
class MyClass {
public:
void timer_event() {
// called by the lambda on the correct instance
foo++;
}
void Setup() {
_timer1s = timerBegin(0, 80, true);
timerAttachInterruptArg(_timer1s, [](void* instance) {
static_cast<MyClass*>(instance)->timer_event();
}, this);
// ...
}
};
评论
0赞
Mark
11/16/2023
谢谢你的提示。我正在挖掘为什么它找不到.我在 ESP32 平台上,它应该在那里。timerAttachInterruptArg
0赞
Ted Lyngmo
11/16/2023
@Mark 不客气!我用我阅读的文档的链接更新了答案。
0赞
Ted Lyngmo
11/16/2023
@Mark 如果你没有它,也许你有一个旧版本的库?cores/esp32/esp32-hal-timer.h
似乎支持我的建议 - 但它不支持边缘触发。timerAttachInterrupt
bool
1赞
Ted Lyngmo
11/16/2023
@Mark 我的建议仅在新的 3.0 API github.com/espressif/arduino-esp32/releases/tag/3.0.0-alpha2 中可用 - 它处于 alpha 状态,但如果您想尝试一下,您需要安装 3.0.0-alpha2 版本(存档列在链接中)。
评论
void(*)()
void(*)()