I am getting the following error: argument of type "void (swarm::*)(const int16_t *rssi_sat, const int16_t *snr, const int16_t *fdev, const uint64_t *msg_id)" is incompatible with parameter of type "void (*)(const int16_t *rssi_sat, const int16_t *snr, const int16_t *fdev, const uint64_t *msg_id)"
This is the setTransmitDataCallback from the sparkfun swarm lib above:
I believe the problem is that the callback function takes a C/C++ function, not a class member.
This is easily solved by making your callback function in your class static. Then have the static function recover the singleton class instance pointer and call a non-static method that does the actual work.
You can tell because the argument passed in is void (swarm::*)( which indicates a class member. The required argument is void (*)( which is a static class member or plain C/C++ function (not in a class).
#ifndef __MYCLASS_H
#define __MYCLASS_H
#include "Particle.h"
/**
* This class is a singleton; you do not create one as a global, on the stack, or with new.
*
* From global application setup you must call:
* MyClass::instance().setup();
*
* From global application loop you must call:
* MyClass::instance().loop();
*/
class MyClass {
public:
/**
* @brief Gets the singleton instance of this class, allocating it if necessary
*
* Use MyClass::instance() to instantiate the singleton.
*/
static MyClass &instance();
/**
* @brief Perform setup operations; call this from global application setup()
*
* You typically use MyClass::instance().setup();
*/
void setup();
/**
* @brief Perform application loop operations; call this from global application loop()
*
* You typically use MyClass::instance().loop();
*/
void loop();
void printMessageSent(const int16_t *rssi_sat, const int16_t *snr, const int16_t *fdev, const uint64_t *msg_id);
static void printMessageSentStatic(const int16_t *rssi_sat, const int16_t *snr, const int16_t *fdev, const uint64_t *msg_id);
protected:
/**
* @brief The constructor is protected because the class is a singleton
*
* Use MyClass::instance() to instantiate the singleton.
*/
MyClass();
/**
* @brief The destructor is protected because the class is a singleton and cannot be deleted
*/
virtual ~MyClass();
/**
* This class is a singleton and cannot be copied
*/
MyClass(const MyClass&) = delete;
/**
* This class is a singleton and cannot be copied
*/
MyClass& operator=(const MyClass&) = delete;
/**
* @brief Singleton instance of this class
*
* The object pointer to this class is stored here. It's NULL at system boot.
*/
static MyClass *_instance;
};
#endif /* __MYCLASS_H */
.cpp file
#include "MyClass.h"
MyClass *MyClass::_instance;
// [static]
MyClass &MyClass::instance() {
if (!_instance) {
_instance = new MyClass();
}
return *_instance;
}
MyClass::MyClass() {
}
MyClass::~MyClass() {
}
void MyClass::setup() {
}
void MyClass::loop() {
// Put your code to run during the application thread loop here
}
void MyClass::printMessageSent(const int16_t *rssi_sat, const int16_t *snr, const int16_t *fdev, const uint64_t *msg_id) {
}
// static
void MyClass::printMessageSentStatic(const int16_t *rssi_sat, const int16_t *snr, const int16_t *fdev, const uint64_t *msg_id) {
instance().printMessageSent(rssi_sat, snr, fdev, msg_id);
}
Just for my own understanding, the instance() is the singleton class instance pointer? I'm assuming I could also use swarm::instance(), but I don't need to because I'm within that singleton anyway?
Yes, but the static member does not know its own instance pointer, so it needs to be stored somewhere.
The technique in my class, allocating the class instance from instance() is the recommended method. It prevents a race condition, and eliminates issues with prohibited calls from global object constructors.
If you allocate your class as a global variable, you can just save the global pointer in _instance from the constructor using: