tags:

views:

240

answers:

4

I need to send floating point numbers using a UDP connection to a Qt application. Now in Qt the only function available is

qint64 readDatagram ( char * data, qint64 maxSize, QHostAddress * address = 0, quint16 * port = 0 )

which accepts data in the form of signed character buffer. I can convert my float into a string and send it but it will obviously not be very efficient converting a 4 byte float into a much longer sized character buffer.

I got hold of these 2 functions to convert a 4 byte float into an unsinged 32 bit integer to transfer over network which works fine for a simple C++ UDP program but for Qt I need to receive the data as unsigned char.

Is it possible to avoid converting the floatinf point data into a string and then sending it?

uint32_t htonf(float f)
{
    uint32_t p;
    uint32_t sign;

    if (f < 0) { sign = 1; f = -f; }
    else { sign = 0; }

    p = ((((uint32_t)f)&0x7fff)<<16) | (sign<<31); // Whole part and sign.
    p |= (uint32_t)(((f - (int)f) * 65536.0f))&0xffff; // Fraction.

    return p;
}

float ntohf(uint32_t p)
{
    float f = ((p>>16)&0x7fff); // Whole part.
    f += (p&0xffff) / 65536.0f; // Fraction.

    if (((p>>31)&0x1) == 0x1) { f = -f; } // Sign bit set.

    return f;
}
A: 

Not sure why the downvote, since the question is vague in requirements.

A 4-byte float is simply a 4 character buffer, if cast as one. If the systems are homogenous, the float can be sent as a signed char *, and bit for bit it'll be the same read into the signed char * on the receiver directly, no conversion needed. If the systems are heterogenous, then this won't work and you need to convert it to a portable format, anyway. IEEE format is often used, but my question is still, what are the requirements, is the float format the same between systems?

mrjoltcola
I am really sorry for the downvote. I dont know I was thinking on some crap lines. It was actually pretty simple just as u said i could obviously treat a signed char as an unsigned char. I accepted the message in a char array and generated an unsigned 32 bit int from it by bit shifting and all. Thanks
A: 

If I read it correctly, your primary question seems to be how to receive data of type unsigned char with QT's readDatagram function which uses a pointer to a buffer of type char.

The short answer is use a cast along these lines:

const size_t MAXSIZE = 1024;
unsigned char* data = malloc(MAXSIZE);

readDatagram ( (unsigned char *)data, MAXSIZE, address, port )

I'm going to assume you have multiple machines which use the same IEEE floating point format but some of which are big endian and some of which are little endian. See this SO post for a good discussion of this issue.

In that case you could do something a bit simpler like this:

const size_t FCOUNT = 256;
float* data = malloc(FCOUNT * sizeof(*data));

readDatagram ( (char *)data, FCOUNT * sizeof(*data), address, port )

for (int i = 0; i != FCOUNT; ++i)
    data[i] = ntohf(*((uint32_t*)&data[i]));

The thing to remember is that as far as networking functions like readDatagram are concerned, the data is just a bunch of bits and it doesn't care what type those bits are interpreted as.

Robert S. Barnes
+1  A: 

Have you tried using readDatagram? Or converting the data to a QByteArray after reading? In many cases a char* is really just a byte array. This is one of those cases. Note that the writeDatagram can take a QByteArray.

Generally every thing sent across sockets is in bytes not strings, layers on either end do the conversions. Take a look here, especially the Broadcaster examples. They show how to create a QByteArray for broadcast and receive.

Adam W
A: 

If both ends of your UDP connection use Qt, I would suggest looking at QDataStream. You can create this from a QByteArray each time you read a datagram, and then read whatever values you require - floats, maps, lists, QVariants, and of course string.

Similarly, on the sending side, you'd create a data stream, push data into it, then send the resulting QByteArray over writeDatagram.

Obviously this only works if both ends use Qt - the data encoding is well-defined, but non-trivial to generate by hand.

(If you want stream orientated behaviour, you could use the fact that QUDPSocket is a QIODevice with a data-stream, but it sounds as if you want per-datagram behaviour)

James Turner