2017-11-20 1 views
2

Ich arbeite an einem Particle project und komme aus JS, so dass ich von Rückrufen in C++ herausgefordert bin. Ich versuche, meine Firebase-Code in eine wiederverwendbare Klasse zu Refactoring und dafür brauche ich Rückrufe:Rückrufe in C++ für ein Arduino-Projekt

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; 
} 

Wenn getDataHandler ist statisch scheint alles zu funktionieren, aber natürlich habe ich Probleme beim Zugriff auf den Rückruf und ich bekomme:

invalid use of member 'Firebase::_readCallback' in static member function

Wenn es nicht statisch ist ich für diese Linie:

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

der folgende Fehler:

invalid use of non-static member function

Wenn ich versuche, es zu binden, wie empfohlen here:

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

I einen Fehlertyp erhalten, da Particle subscribe keine verknüpfte Methode erwartet:

no matching function for call to 'CloudClass::subscribe(const char [25], std::_Bind_helper::type, Spark_Subscription_Scope_TypeDef)'

Gibt es einen Weg um es herum?

+0

Soweit meine C++ Verständnis mir sagt, es ist einige interne Firmware Eventhandler Klasse: https://github.com/ spark/firmware/blob/e854596ef86286a789d19018a136f41cc2fe6f8b/system/src/system_cloud.cpp void eventHandler (system_event_t event, int daten, void *) { – Guy

Antwort

1

Sie erhalten diesen Fehler, weil std::bind ein Funktionsobjekt zurückgibt, das der Signatur void() und nicht void(char const*, char const*) entspricht. Der Grund dafür ist, dass Sie für diese Argumente keine Platzhalter angegeben haben. So eine schnelle Lösung wäre:

Jetzt der Bind-Helfer erwartet zwei Parameter, die es an die gebundene Elementfunktion weiterleiten wird.


, dass alle gesagt haben, gibt es keinen Grund std::bind zu verwenden ist, wenn eine Lambda genügt. Lambdas sind in der Tat in vielerlei Hinsicht überlegen. In C++ 14 gibt es praktisch keinen Grund, std::bind überhaupt zu verwenden. Und auch in C++ 11, kann Ihr Anwendungsfall mit durch einen einfachen Lambda behandelt:

Particle.subscribe("hook-response/test3rdata", [this](char const* a, char const* b) { getDataHandler(a, b); }, MY_DEVICES); 
+0

Awesome! Funktioniert wie erwartet. – Guy