Problem with a data from UDP
-
I get some data
socket->readDatagram(udp_buffer.data(), udp_buffer.size(), &sender, &senderPort);
but the first argument is a char.
qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *host = nullptr, quint16 *port = nullptr);
and I get bytes (uint8_t) - so my data will be trancated?
-
No, it won't. The first argument is a pointer which may point to a string of arbitrary length.
But better just use
receiveDatagram()
https://doc.qt.io/qt-5/qudpsocket.html#receiveDatagram, with that function you can easily read the result as aQByteArray
. -
@jenya7 said in Problem with a data from UDP:
but the first argument is a char.
It isn't. It's a
char *
.and I get bytes (uint8_t)
That will be:
typedef unsigned char uint8_t;
.Size is OK. There will be no "truncation". What type does your
udp_buffer.data()
return anyway? -
It's
QByteArray udp_buffer;
Now I pass it to a parse function
uint32_t MSGPARSER::ParseMessage(QByteArray data, MESSAGE * sens_msg) { if (data[0] == INTERFACE_ID_NONE || data[1] > INTERFACE_ID_RS485) // error: use of erloaded operator '==' is ambiguous (with operand types 'QByteRef' and 'int') return MSG_PARSE_ERROR_WRONG_INTFACE_ID; else sens_msg->interface_id = data[0]; // warning: implicit conversion changes signedness: 'char' to 'uint8_t' (aka 'unsigned char') return 0; }
So data[0] is a char.
-
@jenya7 said in Problem with a data from UDP:
So data[0] is a char.
It's just a collection of 8 bits. UDP makes no assumptions about the data it is transporting. You can cast it to proper type if you know what it is.
-
@sierdzio
So every time I have to cast?if ( static_cast<uint8_t>(data[0]) == INTERFACE_ID_NONE || static_cast<uint8_t>(data[0]) > INTERFACE_ID_RS485) return MSG_PARSE_ERROR_WRONG_INTFACE_ID; else sens_msg->interface_id = static_cast<uint8_t>(data[0]);
It's not convenient at all. I have hundred bytes to parse. The first development environment I see that points char* to a network buffer.
socket->readDatagram( (uint8_t *) udp_buffer.data(), udp_buffer.size(), &sender, &senderPort);
error: cannot initialize a parameter of type 'char *' with an rvalue of type 'uint8_t *' (aka 'unsigned char *')
It should be (void *) in the function prototype.
-
@jenya7
QByteArray
holdschar
s.uint8_t
isunsigned char
. If you compare them directly you are liable to get "unsigned/signed comparison" warnings. As you have seen.If you don't like having to explicitly do casting each time, you could, say, write your own utility function for "the i'th element of a
QByteArray
asunsigned char
/uint_t
", or the whole data asuint_t *
.Separately, your parameter in
ParseMessage(QByteArray data
would be better declared asconst QByteArray &data
. But that won't change the casting issue. -
@jenya7 said in Problem with a data from UDP:
socket->readDatagram( *(uint8_t ) udp_buffer.data(), udp_buffer.size(), &sender, &senderPort);
This should be:
socket->readDatagram( (uint8_t *) udp_buffer.data(), udp_buffer.size(), &sender, &senderPort);
EDIT:
socket->readDatagram( udp_buffer.data(), udp_buffer.size(), &sender, &senderPort);
-
@KroMignon said in Problem with a data from UDP:
@jenya7 said in Problem with a data from UDP:
socket->readDatagram( *(uint8_t ) udp_buffer.data(), udp_buffer.size(), &sender, &senderPort);
This should be:
socket->readDatagram( (uint8_t *) udp_buffer.data(), udp_buffer.size(), &sender, &senderPort);
It is. The editor's problem
-
@KroMignon said in Problem with a data from UDP:
socket->readDatagram( udp_buffer.data(), udp_buffer.size(), &sender, &senderPort);
This way I get array of chars I have to cast every byte.
socket->readDatagram((uint8_t *)udp_buffer.data(), udp_buffer.size(), &sender, &senderPort);
This way - error: cannot initialize a parameter of type 'char *' with an rvalue of type 'uint8_t *' (aka 'unsigned char *')
-
You can use QDataStream to automatically convert all data to whatever format you require. To get a suitable device for it, use QBuffer.
-
@jenya7 said in Problem with a data from UDP:
his way - error: cannot initialize a parameter of type 'char *' with an rvalue of type 'uint8_t *' (aka 'unsigned char *')
What are you doing?
socket
is as instance ofQUdpSocket
andudp_buffer
an instance ofQByteArray
or not?This must work, as I always do it!
QByteArray datagram(socket->pendingDatagramSize(), 0); QHostAddress sender; quint16 senderPort; socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
-
-
@jenya7 said in Problem with a data from UDP:
Yes it is.
But taking char by char form datagram.data()
I have to cast - byte b0 = static_cast<uint8_t>(datagram[0]);No:
for(const auto b : datagram) { qDebug() << "Byte value:" << quint8(b); }
EDIT
oruint8_t* myPoint = static_cast<uint8_t*>(datagram.data());
-
@jenya7
I will contribute one more time. I already told you what to do if you want to reduce repeated casting:If you don't like having to explicitly do casting each time, you could, say, write your own utility function for "the i'th element of a QByteArray as unsigned char/uint_t", or the whole data as uint_t *.
Same applies anywhere else.
For the record: I believe there have been discussions over the years about how some people would have preferred
QByteArray
to holdunsigned char
s instead ofchar
s. It stays withchar
s due (at least partly) to it's (slightly weird) determination to end the data with\0
and allow it to interchange fairly free withQString
. This is not convenient for your case, but it is what it is, so you're going to have to work with it. -
@JonB said in Problem with a data from UDP:
@jenya7
I will contribute one more time. I already told you what to do if you want to reduce repeated casting:If you don't like having to explicitly do casting each time, you could, say, write your own utility function for "the i'th element of a QByteArray as unsigned char/uint_t", or the whole data as uint_t *.
Same applies anywhere else.
To cast each element in a loop? It makes even worse, waste of run time.