C ++:将成员函数作为普通函数指针传递的闭包
Posted
技术标签:
【中文标题】C ++:将成员函数作为普通函数指针传递的闭包【英文标题】:C++: closure to pass member function as normal function pointer 【发布时间】:2014-06-22 15:31:28 【问题描述】:我正在尝试调用以函数指针作为参数的外部库的成员函数:
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(参见“警告”)?
【问题讨论】:
你的编译器是否支持std::mem_fn
,虽然它是 c++11
使用StandardCplusplus Library 有一个类似的端口。
这个问题没有意义。这就像说,“我妻子要我带西红柿回家。我有一盒钉子和一条面包。1.有没有更好的解决方案?2.我怎样才能取悦我的妻子?3.我怎样才能找到一个把钉子和面包当作西红柿的妻子?”
我不明白你的意思@KerrekSB。在我看来,这是一个关于第三方库限制的明确问题。
这正是闭包的用途......将范围/状态封装到一个函数中。你有什么建议?
【参考方案1】:
您的基本问题是您的 Timer
库写得不好:至少应该使用 void(*)(void*), void*
。
如果没有 pvoid 或等效项,除了执行代码中的地址之外,您不能传递任何状态来运行过程。作为一个方法还需要一个 this
指针,你运气不好。
现在,如果您的 MyClass
实例是单例,您可以从其他地方获取 this
。
如果做不到这一点,您需要创建自己的全局状态,以便您从特定回调映射到某个状态。如果您的MyClass
和Timer
的其他消费者数量有限,您可以拥有一些固定的函数,并让它们全局存储它们的额外状态。
这完全是一个黑客行为。接下来的情况更糟。
编写一个具有一些全局状态和void()
接口的动态库。添加回调时,复制该动态库,在运行时修改其全局状态,将其写为不同名称的库,加载它,并将纯回调函数传递给您的 Timer
类。
或者通过手动编写机器代码并将页面标记为可执行来在没有库的情况下进行等效操作。
这些都是糟糕的解决方案。这使我找到了一个好方法:找到更好的Timer
。如果他们搞砸了这么简单的事情,图书馆的其余部分可能也很糟糕。
【讨论】:
感谢您的回复!我想我会从 hack 开始,直到我可以用更好的东西替换它。以上是关于C ++:将成员函数作为普通函数指针传递的闭包的主要内容,如果未能解决你的问题,请参考以下文章