0

I have a small websocket server built with libwebsockets , and I need to receive a string , the problem is that the data received is a *void, but I have trouble to cast it to string .

static int my_protocol_callback(struct libwebsocket_context *context,
             struct libwebsocket *wsi,
             enum libwebsocket_callback_reasons reason,
             void *user, void *in, size_t len)
{
    int n, m;
    unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 +
                          LWS_SEND_BUFFER_POST_PADDING];
    unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];


    switch (reason) {

        case LWS_CALLBACK_ESTABLISHED:
            printf("New Connection\n");
            break;

        case LWS_CALLBACK_SERVER_WRITEABLE:
            break;

        case LWS_CALLBACK_RECEIVE:
            webcmd = static_cast<std::string*>(in);
            break;

        case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
            break;

        default:
            break;
    }
    return 0;
}

under the LWS CALLBACK RECEIVE case, the data is *in, and I casted it by static_cast<std::string*>(in);, stored in the webcmd string.

the problem is that the result is a char pointer, instead I need a true char because next I need to split the string.

what do you think about it?

EDIT : resolved the problem .

Under case LWS_CALLBACK_RECEIVE:

        tmpcmd = reinterpret_cast <char*>(in);
    strcpy(webcmd , tmpcmd );

webcmd is a char array and tmpcmd is a char pointer

thank you for all :D

timrau
  • 22,578
  • 4
  • 51
  • 64

3 Answers3

2

You can't just static_cast to anything you like and hope that it is going to work. Unfortunately you are allowed without warning to cast a void* to anything you like.

static_cast, like reinterpret_cast just changes the type a compile-time without any checks as to whether what is pointed to by the pointer actually represents the type you are casting it to.

In this case, a std::string is a complex type with multiple member variables and memory representation. And unless you passed in exactly the same type, you will have catastrophic results.

It would be much better to pass in the actual type, rather than void*, but I don't know if that is possible with what you are doing.

If you really need a string then you need to use one of std::strings constructors.

Like this:

case LWS_CALLBACK_RECEIVE:
        std::string command(static_cast<char*>(in));
        webcmd = command; //I don't know what webcmd is.
        break;
Salgar
  • 7,687
  • 1
  • 25
  • 39
1

"in" should be some char array , you should do something like this:

char * buf = new char[DATA_SIZE];

and then memory copy the data into it as array of characters (or BYTE).

timrau
  • 22,578
  • 4
  • 51
  • 64
alirakiyan
  • 418
  • 4
  • 16
0

Once something has been cast to a void*, all type information has been lost.

You need to search through the code / documentation that sets up the callback function and convert back to the data type of the instance that was originally cast to the void*. It may well be a std::string*, but could be other types such as a char*. Then, to make your code really clear, use a reinterpret_cast:

whateverthetypeis* = reinterpret_cast<whateverthetypeis*>(in);

These days, callbacks can be modelled as functors or by using templates. Then the type information is preserved. The mechanism you're currently using is a throwback to the old C days when void* was used as a generic type.

As for wanting a true char; you will not get that. A char is just a number between -128 and +127. However a char* (i.e. a char pointer) is used by C and C++ to model a sequence of non-zero characters starting at the memory location denoted by the char*: i.e. a string.

If it turns out that in is a char*, then you can construct a std::string with in as the constructor argument and split the std::string at your leisure.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483