C++ 如何调用 class 中的方法作为 TaskScheduler 的函数指针 - Arduino
C++ How to call methods within a class as function pointer for TaskScheduler - Arduino
我尝试实现一个在 C++ 中调用的任务Class,它需要一个回调函数。由于我是 C++ 的新手,虽然我对指针有粗略的了解,但这是我还无法弄清楚的事情:
我正在使用 TaskScheduler
要设置 class 中所需的一切,我想调用以下函数
arduino 的正常示例不使用 classes,我正在努力让它在我的重构代码中工作。
void Weather::setup(std::shared_ptr<Scheduler> s ,int id, String appid, uint32_t interval)
{
...
weatherTask(interval, TASK_FOREVER, &Weather::updateWeatherCallback, *scheduler, true);
}
updateWeatherCallback 函数也在这个 class 中实现:
void Weather::updateWeatherCallback() {...}
除了使用上面的代码之外,我还尝试了一些在 Whosebug 上建议的 lambda 变体以及以下内容:
weatherTask(interval,TASK_FOREVER, [this](){this->updateWeatherCallback;},*scheduler,true);
但我认为我对 Whosebug 上的这些答案的理解并不好 - 它更多的反复试验 - 这使得搜索 "the right answers" 变得困难
TaskScheduler-Library 中的一些细节:
typedef void (*TaskCallback)();
class Task {
friend class Scheduler;
public:
INLINE Task(unsigned long aInterval=0, long aIterations=0, TaskCallback aCallback=NULL,
Scheduler* aScheduler=NULL, bool aEnable=false, TaskOnEnable aOnEnable=NULL,
TaskOnDisable aOnDisable=NULL);
...
谢谢:)
虽然上面使用函数指针是旧方法,但较新的方法是使用函数对象和 <functional>
库。请参阅 std::function
中的 here for an overview of the entire library, with the examples 提供了很好的 "this is how it works" 教程。
也请查看 lambdas 以了解此类问题。这也很有用,也可以存储在 std::function
中。
weatherTask 需要一个函数指针而不是指向成员的指针。解决此问题的一种可能方法是创建一个辅助结构并将函数绑定到 std::function
.
#include <functional>
template <typename T>
struct Callback;
template <typename Ret, typename... Params>
struct Callback<Ret(Params...)> {
template <typename... Args>
static Ret callback(Args... args) {
func(args...);
}
static std::function<Ret(Params...)> func;
};
template <typename Ret, typename... Params>
std::function<Ret(Params...)> Callback<Ret(Params...)>::func;
创建 weatherTask 时使用以下方法将成员函数绑定到您的回调:
Callback<void(void)>::func = std::bind(&Weather::updateWeatherCallback, this);
TaskCallback func = static_cast<TaskCallback>(Callback<void(void)>::callback);
weatherTask(interval, TASK_FOREVER, func, *scheduler, true);
解决方案是作为 this 问题的答案提出的。由于我无法发表评论,因此我决定提供这个作为答案。
或者,您可以使用类似蹦床的功能。因此,您需要存储一个指向 Weather
对象的全局指针。
Weather global_ptr;
然后您就可以使用 lambda 函数创建 weatherTask
。
weatherTask(interval, TASK_FOREVER, [](){global_ptr->updateWeatherCallback();}, *scheduler, true);
我尝试实现一个在 C++ 中调用的任务Class,它需要一个回调函数。由于我是 C++ 的新手,虽然我对指针有粗略的了解,但这是我还无法弄清楚的事情:
我正在使用 TaskScheduler 要设置 class 中所需的一切,我想调用以下函数 arduino 的正常示例不使用 classes,我正在努力让它在我的重构代码中工作。
void Weather::setup(std::shared_ptr<Scheduler> s ,int id, String appid, uint32_t interval)
{
...
weatherTask(interval, TASK_FOREVER, &Weather::updateWeatherCallback, *scheduler, true);
}
updateWeatherCallback 函数也在这个 class 中实现:
void Weather::updateWeatherCallback() {...}
除了使用上面的代码之外,我还尝试了一些在 Whosebug 上建议的 lambda 变体以及以下内容:
weatherTask(interval,TASK_FOREVER, [this](){this->updateWeatherCallback;},*scheduler,true);
但我认为我对 Whosebug 上的这些答案的理解并不好 - 它更多的反复试验 - 这使得搜索 "the right answers" 变得困难
TaskScheduler-Library 中的一些细节:
typedef void (*TaskCallback)();
class Task {
friend class Scheduler;
public:
INLINE Task(unsigned long aInterval=0, long aIterations=0, TaskCallback aCallback=NULL,
Scheduler* aScheduler=NULL, bool aEnable=false, TaskOnEnable aOnEnable=NULL,
TaskOnDisable aOnDisable=NULL);
...
谢谢:)
虽然上面使用函数指针是旧方法,但较新的方法是使用函数对象和 <functional>
库。请参阅 std::function
中的 here for an overview of the entire library, with the examples 提供了很好的 "this is how it works" 教程。
也请查看 lambdas 以了解此类问题。这也很有用,也可以存储在 std::function
中。
weatherTask 需要一个函数指针而不是指向成员的指针。解决此问题的一种可能方法是创建一个辅助结构并将函数绑定到 std::function
.
#include <functional>
template <typename T>
struct Callback;
template <typename Ret, typename... Params>
struct Callback<Ret(Params...)> {
template <typename... Args>
static Ret callback(Args... args) {
func(args...);
}
static std::function<Ret(Params...)> func;
};
template <typename Ret, typename... Params>
std::function<Ret(Params...)> Callback<Ret(Params...)>::func;
创建 weatherTask 时使用以下方法将成员函数绑定到您的回调:
Callback<void(void)>::func = std::bind(&Weather::updateWeatherCallback, this);
TaskCallback func = static_cast<TaskCallback>(Callback<void(void)>::callback);
weatherTask(interval, TASK_FOREVER, func, *scheduler, true);
解决方案是作为 this 问题的答案提出的。由于我无法发表评论,因此我决定提供这个作为答案。
或者,您可以使用类似蹦床的功能。因此,您需要存储一个指向 Weather
对象的全局指针。
Weather global_ptr;
然后您就可以使用 lambda 函数创建 weatherTask
。
weatherTask(interval, TASK_FOREVER, [](){global_ptr->updateWeatherCallback();}, *scheduler, true);