Как передать нестатический член класса для обратного вызова на платформах avr?

Я использую библиотеку PubSubClient в своей собственной библиотеке Arduino. У меня возникли проблемы с попыткой назначить член класса в качестве функции обратного вызова setCallback клиентской библиотеки.

MyClass.cpp :

#include <PubSubClient.h>
#include <Wifi.h>
#include "Arduino.h"
#include "MyClass.h"

WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

void MyClass::connect(String host, int port) {
  mqttClient.begin(host, port, "/");
  mqttClient.setCallback(incomingEventHandler);
}

void MyClass::loop() {
  mqttClient.loop();
}

void MyClass::incomingEventHandler(char* type, byte *payload, unsigned int length) {
  // делать что-то с входящими данными
  // необходимо получить доступ к другим функциям-членам и переменным класса
}

MyClass.h:

#ifndef MyClass_h
#define MyClass_h

#include <PubSubClient.h>
#include <Wifi.h>
#include "Arduino.h"

class MyClass {
  public:
    void connect(String host, int port);
    void loop();
    void incomingEventHandler(WStype_t type, uint8_t *payload, size_t length);
};

#endif

Ошибка, которую я вижу, заключается в следующем:

sketch/MyClass.cpp: In member function 'void MyClass::connect(String, int)': MyClass.cpp:14:47: error: no matching function for call to 'PubSubClient::setCallback()'
mqttClient.setCallback(incomingEventHandler);

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

В arduino c ++ как я могу передать нестатические свойства члена класса в качестве обратного вызова? Есть ли лучший способ подойти к этому?

P.S. Этот код предназначен только для того, чтобы показать намерение. Возможно, это тоже не будет компиляцией. Был похожий вопрос, подобный этому: Как передать нестатического члена класса в обратный вызов?

но это для esp-8266, а это для платы на базе avrmega4809.

, 👍1

Обсуждение

Лично я обычно пишу небольшую оболочку, которая вызывает функцию для глобального объекта. Либо как обычная функция, либо как статическая функция, если мне когда-либо понадобится только один экземпляр. Грубо, но эффективно., @Majenko


1 ответ


2

Ты не можешь. На платформе AVR PubSubClient::setCallback() ожидает необработанный указатель на функцию в качестве обратного вызова, и это то, что вы должны предоставить. Статический метод эквивалентен необработанной функции, нестатический метод - нет, и ни один из них не является функтором или std::function.

Если вам нужно больше одного объекта MyClass, одним из решений может быть изменение библиотеки pubsubclient, чтобы она сохраняла указатель на ваш экземпляр MyClass и передавала этот указатель вашему обратному вызову. Если вам никогда не приходилось, чтобы экземпляры MyClass подписывались на один и тот же раздел, лучшим решением может быть статическое сохранение сопоставления между разделами и экземплярами MyClass и, в рамках обратного вызова, использование этой сопоставления для поиска соответствующего экземпляра.

,

Технически вы можете это сделать, но не без изменения библиотеки. Самым простым способом было бы чисто определить класс виртуального интерфейса и наследовать от него и переопределить метод обратного вызова. Другим способом было бы https://www.tutorialspoint.com/function-pointer-to-member-function-in-cplusplus (изменения, аналогичные первому способу), @KIIV