Arduino 项目的 C++ 回调
Callbacks in C++ for an Arduino project
我正在研究 Particle project 并且来自 JS,所以我受到 C++ 回调的挑战。我正在尝试将我的 Firebase 代码重构为可重用的 class,为此我需要回调:
void setup() {
firebase = new Firebase;
Serial.begin(9600);
firebase->subscribe();
firebase->setCallback(readCallback);
}
void readCallback(JsonObject& root)
{
r = root["r"];
g = root["g"];
b = root["b"];
Serial.printlnf("Yes! r=%d g=%d b=%d d=%d", r, g, b);
}
Firebase.h:
#ifndef Firebase_h
#define Firebase_h
#include <SparkJson.h>
class Firebase {
public:
Firebase();
void
subscribe(),
setCallback(void (*readCallback)(JsonObject& root));
private:
static void getDataHandler(const char *topic, const char *data);
void (*_readCallback)(JsonObject& root);
};
#endif
Firebase.m:
#include "Particle.h"
// This #include statement was automatically added by the Particle IDE.
#include <SparkJson.h>
#include "ArduinoJson.h"
#include "Firebase.h"
Firebase::Firebase(void) {
Serial.printlnf("Firebase instance created");
}
void Firebase::getDataHandler(const char *topic, const char *data) {
Serial.printlnf("getDataHandler invoked");
StaticJsonBuffer<256> jsonBuffer;
char *mutableCopy = strdup(data);
JsonObject& root = jsonBuffer.parseObject(mutableCopy);
free(mutableCopy);
Serial.printlnf("data received: %s", data);
// _readCallback(root);
}
void Firebase::subscribe() {
Serial.printlnf("Firebase subscribe");
Particle.subscribe("hook-response/test3rdata", getDataHandler, MY_DEVICES);
}
void Firebase::setCallback(void (*readCallback)(JsonObject& root))
{
Serial.printlnf("set callback");
_readCallback = readCallback;
}
当 getDataHandler 是静态的时,一切似乎都能正常工作,但我自然无法访问回调,我得到:
invalid use of member 'Firebase::_readCallback' in static member
function
当它不是静态的时,我得到这一行:
Particle.subscribe("hook-response/test3rdata", getDataHandler, MY_DEVICES);
出现以下错误:
invalid use of non-static member function
当我尝试按照建议绑定它时:
Particle.subscribe("hook-response/test3rdata", std::bind(&Firebase::getDataHandler,this), MY_DEVICES);
我输入错误,因为 Particle.subscribe 不需要绑定方法:
no matching function for call to 'CloudClass::subscribe(const char
[25], std::_Bind_helper::type, Spark_Subscription_Scope_TypeDef)'
有解决办法吗?
您收到此错误是因为 std::bind
returns 函数对象遵循签名 void()
而不是 void(char const*, char const*)
。原因是,您没有为这些参数指定任何占位符。所以一个快速的解决办法是:
std::bind(&Firebase::getDataHandler, this, std::placeholders::_1, std::placeholders::_2)
现在绑定助手需要两个参数,它将转发给绑定的成员函数。
话虽如此,如果 lambda 就足够了,就没有理由使用 std::bind
。 Lambda 实际上在大多数方面都更胜一筹。在 C++14 中,几乎没有理由使用 std::bind
。即使在 C++11 中,您的用例也可以通过一个简单的 lambda 来处理:
Particle.subscribe("hook-response/test3rdata", [this](char const* a, char const* b) { getDataHandler(a, b); }, MY_DEVICES);
我正在研究 Particle project 并且来自 JS,所以我受到 C++ 回调的挑战。我正在尝试将我的 Firebase 代码重构为可重用的 class,为此我需要回调:
void setup() {
firebase = new Firebase;
Serial.begin(9600);
firebase->subscribe();
firebase->setCallback(readCallback);
}
void readCallback(JsonObject& root)
{
r = root["r"];
g = root["g"];
b = root["b"];
Serial.printlnf("Yes! r=%d g=%d b=%d d=%d", r, g, b);
}
Firebase.h:
#ifndef Firebase_h
#define Firebase_h
#include <SparkJson.h>
class Firebase {
public:
Firebase();
void
subscribe(),
setCallback(void (*readCallback)(JsonObject& root));
private:
static void getDataHandler(const char *topic, const char *data);
void (*_readCallback)(JsonObject& root);
};
#endif
Firebase.m:
#include "Particle.h"
// This #include statement was automatically added by the Particle IDE.
#include <SparkJson.h>
#include "ArduinoJson.h"
#include "Firebase.h"
Firebase::Firebase(void) {
Serial.printlnf("Firebase instance created");
}
void Firebase::getDataHandler(const char *topic, const char *data) {
Serial.printlnf("getDataHandler invoked");
StaticJsonBuffer<256> jsonBuffer;
char *mutableCopy = strdup(data);
JsonObject& root = jsonBuffer.parseObject(mutableCopy);
free(mutableCopy);
Serial.printlnf("data received: %s", data);
// _readCallback(root);
}
void Firebase::subscribe() {
Serial.printlnf("Firebase subscribe");
Particle.subscribe("hook-response/test3rdata", getDataHandler, MY_DEVICES);
}
void Firebase::setCallback(void (*readCallback)(JsonObject& root))
{
Serial.printlnf("set callback");
_readCallback = readCallback;
}
当 getDataHandler 是静态的时,一切似乎都能正常工作,但我自然无法访问回调,我得到:
invalid use of member 'Firebase::_readCallback' in static member function
当它不是静态的时,我得到这一行:
Particle.subscribe("hook-response/test3rdata", getDataHandler, MY_DEVICES);
出现以下错误:
invalid use of non-static member function
当我尝试按照建议绑定它时
Particle.subscribe("hook-response/test3rdata", std::bind(&Firebase::getDataHandler,this), MY_DEVICES);
我输入错误,因为 Particle.subscribe 不需要绑定方法:
no matching function for call to 'CloudClass::subscribe(const char [25], std::_Bind_helper::type, Spark_Subscription_Scope_TypeDef)'
有解决办法吗?
您收到此错误是因为 std::bind
returns 函数对象遵循签名 void()
而不是 void(char const*, char const*)
。原因是,您没有为这些参数指定任何占位符。所以一个快速的解决办法是:
std::bind(&Firebase::getDataHandler, this, std::placeholders::_1, std::placeholders::_2)
现在绑定助手需要两个参数,它将转发给绑定的成员函数。
话虽如此,如果 lambda 就足够了,就没有理由使用 std::bind
。 Lambda 实际上在大多数方面都更胜一筹。在 C++14 中,几乎没有理由使用 std::bind
。即使在 C++11 中,您的用例也可以通过一个简单的 lambda 来处理:
Particle.subscribe("hook-response/test3rdata", [this](char const* a, char const* b) { getDataHandler(a, b); }, MY_DEVICES);