简体   繁体   中英

Using member function as a callback

I want to pass the method Connection::onWebSocketEvent as an argument to this->ws.onEvent() , but it doesn't work. I'm new to C++. What am I doing wrong?

void Connection::connect(String host, int port, String fingerprint, String token) {
  Serial.println(String("Connect to wss://")+host+":"+port+" with token "+token);
  this->host = host;
  this->port = port;
  this->fingerprint = fingerprint;
  this->token = token;

  this->ws.protocol = "io-json-v1";
  this->ws.beginSSL(this->host, this->port, "/channel", this->fingerprint);

// attempt 1
//  this->ws.onEvent(std::bind(&Connection::onWebSocketEvent, this));

// attempt 2
  this->ws.onEvent([&](WStype_t type, uint8_t* payload, size_t length) {
    this->onWebSocketEvent(type, payload, length);
  });
}

void Connection::onWebSocketEvent(WStype_t type, uint8_t* payload, size_t length) {
  // ...
}

The method header for WebSocketsClient::onEvent is:

typedef void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length);
void onEvent(WebSocketClientEvent cbEvent);

On my first attempt I get this error:

IO.cpp: In member function 'void Connection::connect(String, int, String, String)':
IO.cpp:16: error: no matching function for call to 'WebSocketsClient::onEvent(std::_Bind_helper<false, void (Connection::*)(WStype_t, unsigned char*, unsigned int), Connection* const>::type)'
   this->ws.onEvent(std::bind(&Connection::onWebSocketEvent, this));
                                                                  ^
IO.cpp:16:66: note: candidate is:
In file included from IO.h:7:0,
                 from IO.cpp:1:
/Users/chris/Documents/Arduino/libraries/arduinoWebSockets/src/WebSocketsClient.h:50:14: note: void WebSocketsClient::onEvent(WebSocketsClient::WebSocketClientEvent)
         void onEvent(WebSocketClientEvent cbEvent);
              ^
/Users/chris/Documents/Arduino/libraries/arduinoWebSockets/src/WebSocketsClient.h:50:14: note:   no known conversion for argument 1 from 'std::_Bind_helper<false, void (Connection::*)(WStype_t, unsigned char*, unsigned int), Connection* const>::type {aka std::_Bind<std::_Mem_fn<void (Connection::*)(WStype_t, unsigned char*, unsigned int)>(Connection*)>}' to 'WebSocketsClient::WebSocketClientEvent {aka void (*)(WStype_t, unsigned char*, unsigned int)}'
no matching function for call to 'WebSocketsClient::onEvent(std::_Bind_helper<false, void (Connection::*)(WStype_t, unsigned char*, unsigned int), Connection* const>::type)'

On the second:

IO.cpp: In member function 'void Connection::connect(String, int, String, String)':
IO.cpp:20: error: no matching function for call to 'WebSocketsClient::onEvent(Connection::connect(String, int, String, String)::__lambda0)'
   });
    ^
IO.cpp:20:4: note: candidate is:
In file included from IO.h:7:0,
                 from IO.cpp:1:
/Users/chris/Documents/Arduino/libraries/arduinoWebSockets/src/WebSocketsClient.h:50:14: note: void WebSocketsClient::onEvent(WebSocketsClient::WebSocketClientEvent)
         void onEvent(WebSocketClientEvent cbEvent);
              ^
/Users/chris/Documents/Arduino/libraries/arduinoWebSockets/src/WebSocketsClient.h:50:14: note:   no known conversion for argument 1 from 'Connection::connect(String, int, String, String)::__lambda0' to 'WebSocketsClient::WebSocketClientEvent {aka void (*)(WStype_t, unsigned char*, unsigned int)}'
no matching function for call to 'WebSocketsClient::onEvent(Connection::connect(String, int, String, String)::__lambda0)'

You cannot pass a pointer to member function as a simple pointer to function argument since a pointer to member function requires the callback to be called on a valid class instance.

The argument type

void(*)(WStype_t type, uint8_t * payload, size_t length)

does not permit

void (Connection::*)(WStype_t type, uint8_t* payload, size_t length)

which is the type of a pointer to Connection::onWebSocketEvent and a lambda cannot convert to a function pointer unless it does not capture anything.

The trouble here is that you'd get some kind of a circular dependency between the type of ws and Connection and things start to get uneasy, if you want the type of ws to be aware of the current Connection instance.

Try this one:

using namespace std::placeholders;

...

this->ws.onEvent(std::bind(&Connection::onWebSocketEvent, this, _1, _2, _3))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM