我正在尝试调用外部库的成员函数,该函数接受函数指针作为参数:
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();})
}
编译器输出:
警告:警告:lambda 表达式仅适用于 -std=c++11 或 -std=gnu++11 [默认启用]
错误:没有匹配的函数可用于调用“Timer::every(int, MyClass::MyClass()::__lambda0)”
- 还有其他/更好的解决方案吗?
- 关于我当前的方法:(如何)当需要函数指针时是否可以传递对 lambda 的引用?
- 我如何查明 Arduino/AVR 是否支持这些 lambda(请参阅“警告”)?
你的基本问题是你的Timer
图书馆写得不好:应该采取void(*)(void*), void*
至少。
如果没有 pvoid 或等效项,则无法传递除执行代码中的地址之外的任何状态来运行过程。作为一种方法也重新布线this
指针,你运气不好。
现在,如果你的实例MyClass
是一个单例,你可以得到this
从其他地方。
如果做不到这一点,您需要创建自己的全局状态,以便您可以从特定回调映射到某个状态。如果你的数量有限MyClass
以及其他消费者Timer
,您可以拥有一些固定函数,并让它们在全局范围内存储额外的状态。
这都是黑客行为。接下来的情况更糟。
编写一个具有某些全局状态的动态库,以及void()
界面。添加回调时,复制该动态库,在运行时修改其全局状态,将其写为不同名称的库,加载它,并将纯回调函数传递给您的Timer
class.
或者在没有库的情况下通过手动编写机器代码并将页面标记为可执行文件来执行等效操作。
这些都是糟糕的解决方案。这让我找到了一个好的办法:找到一个更好的Timer
。如果他们搞砸了这么简单的事情,那么图书馆的其他部分也可能很糟糕。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)