(udp) convert one QByteArray to multiple structs ?
-
Hi eveyone,
I'm learning c++ and I try to make my own telemetry application for F1 2018 as the game can send its data via UDP.
The reception works fine, but I don't know how I can convert the QByteArray that readDatagram() gives me.The data is sent using multiple structs, some are inside others, here's the doc : link to CodeMaster's forum thread. For example, the speed of the car is in the CarTelemetryData struct that is in the PacketCarTelemetryData struct, I know I can do PacketCarTelemetryData->CarTelemetryData->m_speed to get it but when I do it, the app crashes with no error. The variables types are all the same both in the .h and .cpp.
(I just tried to put all the structures in one, and use reinterpret_cast to this new one but still the same problem ...)My question is : is there any way I can "cast" (or whatever) my datagram to my multiple structures ?
Thanks a lot !
ps: tell me if you don't understand, also my structs file is 260 lines long so I assume it's better to copy to something like pastebin ?
-
Hi,
First of all, look in the debugger to see how the data are arranged, if it looks correct or messy.
There are several possible issues in your case.
- how the data structures are packed, also called Data structure alignment
You may need to specified it with the structs def in the .h file
see: http://www.cplusplus.com/forum/general/14659/ - you may have to care about the endianness and possibly do some conversion regarding the host architecture.
Looking at the link your provide above, i don't see any information about the data alignment and the endianess, unfortunatly.
Maybe i'm out of the subject, i don't know ;)
- how the data structures are packed, also called Data structure alignment
-
Hi eveyone,
I'm learning c++ and I try to make my own telemetry application for F1 2018 as the game can send its data via UDP.
The reception works fine, but I don't know how I can convert the QByteArray that readDatagram() gives me.The data is sent using multiple structs, some are inside others, here's the doc : link to CodeMaster's forum thread. For example, the speed of the car is in the CarTelemetryData struct that is in the PacketCarTelemetryData struct, I know I can do PacketCarTelemetryData->CarTelemetryData->m_speed to get it but when I do it, the app crashes with no error. The variables types are all the same both in the .h and .cpp.
(I just tried to put all the structures in one, and use reinterpret_cast to this new one but still the same problem ...)My question is : is there any way I can "cast" (or whatever) my datagram to my multiple structures ?
Thanks a lot !
ps: tell me if you don't understand, also my structs file is 260 lines long so I assume it's better to copy to something like pastebin ?
Hi @Natalya
Have you thought about using QDataStream ?
If you provide>>
overloads for QDataStream and your structs, you should be able to „stream“ the data from your QByteArray into your structs.What @mpergand said still applies, so keep that in mind.
Usefull links:
http://doc.qt.io/qt-5/qdatastream.html
https://www.qtcentre.org/threads/15168-QDataStream-class-struct-amp-stream-operators -
Hi @mpergand and @J-Hilk
I took a look in the debugger, I have 'SIGSEGV Segmentation Fault' error on an empty line after commented lines what ever i do ... I've read that it have something to do with the pointers ?
And sorry, but I don't understand how to use QDataStream :/
But thanks to you guys.
-
@Natalya said in (udp) convert one QByteArray to multiple structs ?:
I have 'SIGSEGV Segmentation Fault' error on an empty line after commented lines what ever i do
Yes, you and i already know that :)
The point is why.
If you put a breakpoint just after the struct pointer affectation, then in the debugger you can look at the struct field values.The first value you can check is the m_packetFormat field, it must be 2018 (0x7E2)
Any other value means something wrong occured. -
Hi @mpergand and @J-Hilk
I took a look in the debugger, I have 'SIGSEGV Segmentation Fault' error on an empty line after commented lines what ever i do ... I've read that it have something to do with the pointers ?
And sorry, but I don't understand how to use QDataStream :/
But thanks to you guys.
@Natalya said in (udp) convert one QByteArray to multiple structs ?:
And sorry, but I don't understand how to use QDataStream :/
here,
to pratice with:
//PacketHeader.h #ifndef PACKETHEADER_H #define PACKETHEADER_H #include <cstdint> #include <QDataStream> struct PacketHeader { uint16_t m_packetFormat; // 2018 uint8_t m_packetVersion; // Version of this packet type, all start from 1 uint8_t m_packetId; // Identifier for the packet type, see below uint64_t m_sessionUID; // Unique identifier for the session float m_sessionTime; // Session timestamp uint16_t m_frameIdentifier; // Identifier for the frame the data was retrieved on uint8_t m_playerCarIndex; // Index of player's car in the array friend QDataStream& operator<<(QDataStream &out, const PacketHeader &p); friend QDataStream& operator>>(QDataStream &in, PacketHeader &p); }; #endif // PACKETHEADER_H
//PacketHeader.cpp #include "packetheader.h" QDataStream &operator<<(QDataStream &out, const PacketHeader &p) { out << p.m_packetFormat // 2018 << p.m_packetVersion // Version of this packet type, all start from 1 << p.m_packetId // Identifier for the packet type, see below << p.m_sessionUID // Unique identifier for the session << p.m_sessionTime // Session timestamp << p.m_frameIdentifier // Identifier for the frame the data was retrieved on << p.m_playerCarIndex; // Index of player's car in the array return out; } QDataStream &operator>>(QDataStream &in, PacketHeader &p) { in >> p.m_packetFormat // 2018 >> p.m_packetVersion // Version of this packet type, all start from 1 >> p.m_packetId // Identifier for the packet type, see below >> p.m_sessionUID // Unique identifier for the session >> p.m_sessionTime // Session timestamp >> p.m_frameIdentifier // Identifier for the frame the data was retrieved on >> p.m_playerCarIndex; // Index of player's car in the array return in; }
//main int main(int argc, char *argv[]) { QApplication a(argc, argv); PacketHeader p; p.m_playerCarIndex = 5; qDebug() << p.m_playerCarIndex; QByteArray ba; QDataStream in(&ba, QIODevice::WriteOnly); in << p; qDebug() << ba; PacketHeader p2; QDataStream Out(ba); Out >> p2; qDebug() << p2.m_playerCarIndex; return a.exec(); } //Console output to see that its written and read 5 "4m\xC0s\x00\xB5\xFD\xE0\x00\x00\x00\x01""Fx\x07U\xA0\x00\x00\x00]\x04\x05" 5
-
@J-Hilk Thanks, I'll look at that
@mpergand the error keeps happening, I've made a new struct containing all the others (not the ones like telemetry that is only in PacketTelemetry of course) and I displayed that value, I've got '0xffffffe2' for the entire structure and so for the entire datagram ...
I think that my part where I receive is wrong, like if it was cutting the data. I have a datagram.resize() to what looks like to be the received datagram's size, and it works on my 2017 version but not here...I'm quite lost to be honest
-
looking at the faqs, i see:
What encoding format is used?
All values are encoded using Little Endian format.Is the data packed?
Yes, all data is packed.Some code trying to simulate the stuation:
struct PacketHeader { uint16_t m_packetFormat; // 2018 uint8_t m_packetVersion; // Version of this packet type, all start from 1 uint8_t m_packetId; // Identifier for the packet type, see below uint64_t m_sessionUID; // Unique identifier for the session float m_sessionTime; // Session timestamp uint m_frameIdentifier; // Identifier for the frame the data was retrieved on uint8_t m_playerCarIndex; // Index of player's car in the array }; struct Packet { struct PacketHeader p; uint8_t m; }; int main(int argc, char *argv[]) { QByteArray dat; dat.append(226); // 2018 intel format dat.append(7); dat.append(1); // version dat.append(2); // id Packet* pa=(Packet*)dat.data(); qDebug()<<dat; qDebug()<<pa->p.m_packetFormat;
What i see in the debugger:
dat @0x7fff5fbffb88 QByteArray d (hex) 0 QByteArray::Data size 4 int alloc 8 int pa @0x7fff5fbffb70 Packet m 0 uint8_t p @0x10b804228 PacketHeader m_frameIdentifier 4026531840 uint m_packetFormat 2018 uint16_t m_packetId 2 uint8_t m_packetVersion 1 uint8_t m_playerCarIndex 88 uint8_t m_sessionTime 0.0 float m_sessionUID 4487907200 uint64_t
and with qDebug message:
qDebug()<<dat; qDebug()<<pa->p.m_packetFormat; results: "\xE2\x07\x01\x02" 2018