Skip to content

Extend usage of std::function on all the platforms where it's available#993

Open
alranel wants to merge 1 commit intoknolleary:masterfrom
alranel:patch-1
Open

Extend usage of std::function on all the platforms where it's available#993
alranel wants to merge 1 commit intoknolleary:masterfrom
alranel:patch-1

Conversation

@alranel
Copy link
Copy Markdown

@alranel alranel commented Jan 25, 2023

At this point in time, C++11 is available on most Arduino platforms and not just on ESP8266 and ESP32.
With this pull request, the ability to supply lambdas (including object methods) to setCallback() instead of plain function pointers is extended automatically to all the platforms which provide support for std::function. :)

@imbeacon
Copy link
Copy Markdown

Hi, faced the issue with the same reason, on Arduino Nano Connect, based on RP2040.
@knolleary, please add ability to use std::function as callbacks not just for ESP-based boards.

@manchoz
Copy link
Copy Markdown

manchoz commented Feb 21, 2023

+1

@lucae98
Copy link
Copy Markdown

lucae98 commented Jul 12, 2025

Hi everyone,

I’m using PubSubClient version 2.8 on an Arduino Opta WiFi board (not ESP32/ESP8266). I want to set a callback using a lambda with capture ([this]), like this:

clientMQTT.setCallback([this](char* topic, uint8_t* payload, unsigned int length) { this->optaCallback(topic, payload, length); });

However, I get the following compilation error:

error: no matching function for call to 'PubSubClient::setCallback(OptaMQTT::begin()::<lambda(char*, uint8_t*, unsigned int)>)'
{ this->optaCallback(topic, payload, length); });

My compiler uses the flag -std=gnu++14, so lambdas with captures should be supported.

Looking into the library header, I found this conditional macro:

#if defined(ESP8266) || defined(ESP32) #include <functional> #define MQTT_CALLBACK_SIGNATURE std::function<void(char *, uint8_t *, unsigned int)> callback #else #define MQTT_CALLBACK_SIGNATURE void (*callback)(char *, uint8_t *, unsigned int) #endif

So it seems that only on ESP8266/ESP32 the library uses std::function for callbacks (allowing lambdas with captures), and on other platforms like Arduino Opta WiFi it falls back to plain function pointers.

My questions are:

  • Does PubSubClient support lambdas with captures as callbacks on Arduino Opta WiFi?

  • If not, are there plans to support this in the future?

  • How do you usually handle callback functions on non-ESP boards with this library?

Thanks for any insights!

@hmueller01
Copy link
Copy Markdown

@lucae98 Can you please try https://github.com/hmueller01/pubsubclient3 on this. If your platform supports functional this will be used now (not only on ESP platforms) ...

#if defined(__has_include) && __has_include(<functional>) && !defined(NOFUNCTIONAL)
#include <functional>
#define MQTT_CALLBACK_SIGNATURE std::function<void(char* topic, uint8_t* payload, size_t plength)> callback
#else
#define MQTT_CALLBACK_SIGNATURE void (*callback)(char* topic, uint8_t* payload, size_t plength)
#endif

@lucae98
Copy link
Copy Markdown

lucae98 commented Jul 14, 2025

@hmueller01 Thanks for your fast response!
I used this version (https://github.com/hmueller01/pubsubclient3), and the compile error is gone. I’ll test it on my Opta WiFi, but first I need to finish my MQTT implementation.
If I detect any issues, I’ll post them here.

@lucae98
Copy link
Copy Markdown

lucae98 commented Oct 24, 2025

Hi everyone,

I’m using PubSubClient version 2.8 on an Arduino Opta WiFi board (not ESP32/ESP8266). I want to set a callback using a lambda with capture ([this]), like this:

clientMQTT.setCallback([this](char* topic, uint8_t* payload, unsigned int length) { this->optaCallback(topic, payload, length); });

However, I get the following compilation error:

error: no matching function for call to 'PubSubClient::setCallback(OptaMQTT::begin()::<lambda(char*, uint8_t*, unsigned int)>)' { this->optaCallback(topic, payload, length); });

My compiler uses the flag -std=gnu++14, so lambdas with captures should be supported.

Looking into the library header, I found this conditional macro:

#if defined(ESP8266) || defined(ESP32) #include <functional> #define MQTT_CALLBACK_SIGNATURE std::function<void(char *, uint8_t *, unsigned int)> callback #else #define MQTT_CALLBACK_SIGNATURE void (*callback)(char *, uint8_t *, unsigned int) #endif

So it seems that only on ESP8266/ESP32 the library uses std::function for callbacks (allowing lambdas with captures), and on other platforms like Arduino Opta WiFi it falls back to plain function pointers.

My questions are:

  • Does PubSubClient support lambdas with captures as callbacks on Arduino Opta WiFi?
  • If not, are there plans to support this in the future?
  • How do you usually handle callback functions on non-ESP boards with this library?

Thanks for any insights!

For your information: I got it working now.

Tested on the Opta WiFi using the Mosquitto broker.
I used a lambda with capture ([this]) to forward the callback into my class method, which keeps the implementation fully OOP-friendly, like this:

clientMQTT.setCallback([this](char* topic, uint8_t* payload, unsigned int length) { this->optaCallback(topic, payload, length); });

No issues with version 3.1.0.
Thanks

@hmueller01
Copy link
Copy Markdown

Hint: On PubSubClient3 you should use size_t length instead of unsigned int length to make 100% sure that you really use the same "size".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants