Обратные вызовы в C++ для проекта Arduino

Я работаю над проектом Particle и прихожу из JS, поэтому мне бросают вызов обратные вызовы в C++. Я пытаюсь преобразовать мой код Firebase в повторно используемый класс, и для этого мне нужны обратные вызовы:

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 статичен, кажется, что все работает, но, естественно, у меня возникают проблемы с доступом к обратному вызову, и я получаю:

недопустимое использование члена 'Firebase::_readCallback' в статической функции-члене

Когда это не статично, я получаю для этой строки:

Particle.subscribe("hook-response/test3rdata", getDataHandler, MY_DEVICES);

следующая ошибка:

недопустимое использование нестатической функции-члена

Когда я пытаюсь связать это как советовано здесь:

Particle.subscribe("hook-response/test3rdata", std::bind(&Firebase::getDataHandler,this), MY_DEVICES);

Я получаю опечатку, так как Particle.subscribe не ожидает связанного метода:

нет соответствующей функции для вызова CloudClass:: подписка (const char [25], std::_Bind_helper::type, Spark_Subscription_Scope_TypeDef)'

Есть ли способ обойти это?

1 ответ

Решение

Вы получаете эту ошибку, потому что std::bind возвращает объект функции, который придерживается подписи void() и не void(char const*, char const*), Причина в том, что вы не указали никаких заполнителей для этих аргументов. Таким образом, быстрое решение будет:

std::bind(&Firebase::getDataHandler, this, std::placeholders::_1, std::placeholders::_2)

Теперь помощник bind ожидает два параметра, которые он будет перенаправлять в связанную функцию-член.


Сказав все это, нет смысла использовать std::bind если лямбда будет достаточно. Лямбды на самом деле превосходят во многих отношениях. В C++14 практически нет причин использовать std::bind совсем. И даже в C++11 ваш вариант использования может быть обработан простой лямбда-выражением:

Particle.subscribe("hook-response/test3rdata", [this](char const* a, char const* b) { getDataHandler(a, b); }, MY_DEVICES);
Другие вопросы по тегам