I am trying to implement Websocket client using Cpprest sdk (Casablanca). I am successful in establishing the Web Socket connection and able to send/recieve messages. The response is received as an instance of websocket_incoming_message, which has a method, extract_string() whose definition is,

_ASYNCRTIMP pplx::task<std::string> web::websockets::client::websocket_incoming_message::extract_string (       )   const

Hence it returns, const string.

I am trying to assign this string to a function local string variable, so that I can return it to the calling method. However, I receive the below error,

error: passing ‘const string {aka const std::basic_string<char>}’ as ‘this’ argument of ‘std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ discards qualifiers [-fpermissive]

Below is my code block,

   std::string WebSocketUtility::send_command(const char* command){

    websocket_outgoing_message o_msg;
     std::string ws_response;

    o_msg.set_utf8_message(command);
    client->send(o_msg).then([](){
        log("Message Sent!!!\n");
    });

    client->receive().then([ws_response](websocket_incoming_message i_msg){ 
           return i_msg.extract_string();
        }).then([ws_response](std::string ws_body){ 
                 ws_response = ws_body;  
        });

   log("WS_RESPONSE:%s:\n",ws_response.c_str());
    return ws_response;
  }

I have tried
1.Declaring ws_response as a reference
2.Capturing ws_response as a reference in lambda
3.Declaring ws_response as cpprest json, and assigning the response as a json field (ws_response[U("output")] = json::value::string(ws_body.c_str()))

with no luck.

I do not have much coding experience in C++ and struggling with this.

Could someone please help me on how to capture this response outside the lambda so that I can return the value to the calling method?

Thanks & Regards,
Swathi Desai

1

There are 1 best solutions below

4
Remy Lebeau On

[ws_response](websocket_incoming_message i_msg){ return i_msg.extract_string(); }

There is no reason for the above lambda to capture ws_response at all, as it does not use ws_response for anything.

[ws_response](std::string ws_body){ ws_response = ws_body; }

The above lambda needs to capture ws_response by reference in order to modify it properly. The way the lambda is currently coded, it captures a copy of ws_response by value, and that copy is const since the lambda is not declared as mutable. This is why you are getting the compiler error - you are trying to assign ws_body to a const std::string object that is local to the lambda, not to the ws_response variable that is declared in send_command(). The above lambda is roughly equivalent to this:

const std::string ws_response_copy = ws_response;
ws_response_copy = ws_body; // <-- ERROR

Try this instead:

client->receive().then([](websocket_incoming_message i_msg){ 
    return i_msg.extract_string();
}).then([&ws_response](std::string ws_body){ 
    ws_response = ws_body;  
});

Alternatively, extract_string() returns a pplx::task<std::string>, which has a get() method to retrieve the actual std::string, waiting until it is available. So the above can be simplified to the following:

client->receive().then([&ws_response](websocket_incoming_message i_msg){ 
    ws_response = i_msg.extract_string().get();
});