The solution to this is called serialization
serialization is the process of translating data structures or object state into a format that can be stored (for example, in a file or memory buffer, or transmitted across a network connection link) and reconstructed later in the same or another computer environment.
The following is a fully working example how to serialize the mentioned struct using QDataStream:
// main.cpp
#include <limits>
#include <QDataStream>
#include <QVector>
#include <vector>
typedef struct myStruct
{
int nb_trame;
std::vector<bool> vBool;
std::vector<int> vInt;
std::vector<float> vFloat;
void serialize(QDataStream &out) {
out << nb_trame;
out << QVector<bool>::fromStdVector(vBool);
out << QVector<qint32>::fromStdVector(vInt);
out << QVector<float>::fromStdVector(vFloat);
}
} myStruct;
void fillData(myStruct &s) {
s.nb_trame = 0x42;
s.vBool.push_back(true);
s.vBool.push_back(false);
s.vBool.push_back(false);
s.vBool.push_back(true);
s.vInt.push_back(0xB0);
s.vInt.push_back(0xB1);
s.vInt.push_back(0xB2);
s.vInt.push_back(0xB3);
s.vFloat.push_back(std::numeric_limits<float>::min());
s.vFloat.push_back(0.0);
s.vFloat.push_back(std::numeric_limits<float>::max());
}
int main()
{
myStruct s;
fillData(s);
QByteArray buf;
QDataStream out(&buf, QIODevice::WriteOnly);
s.serialize(out);
}
Then you can send buf
with QUdpSocket::writeDatagram()
How QDataStream
serializes
If we replace
QByteArray buf;
QDataStream out(&buf, QIODevice::WriteOnly);
with
QFile file("file.dat");
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
The serialized data gets written to the file "file.dat". This is the data the code above generates:
> hexdump -C file.dat
00000000 00 00 00 42 00 00 00 04 01 00 00 01 00 00 00 04 |...B............|
00000010 00 00 00 b0 00 00 00 b1 00 00 00 b2 00 00 00 b3 |................|
00000020 00 00 00 03 38 10 00 00 00 00 00 00 00 00 00 00 |....8...........|
00000030 00 00 00 00 47 ef ff ff e0 00 00 00 |....G.......|
- The data starts with four bytes that represent the member nb_trame (
00 00 00 42
)
- The next eight bytes are the serialized form of the vector vBool (
00 00 00 04 01 00 00 01
)
00 00 00 04
--> Number of entries in the vector
01 00 00 01
--> True, False, False, True
- The next 20 bytes are for vInt (
00 00 00 04 00 00 00 b0 00 00 00 b1 00 00 00 b2 00 00 00 b3
)
00 00 00 04
--> Number of entries in the vector
00 00 00 b0 00 00 00 b1 00 00 00 b2 00 00 00 b3
--> 0xB0, 0xB1, 0xB2, 0xB3 (4 bytes per entry)
- The next 28 bytes are for vFloat (
00 00 00 03 38 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 47 ef ff ff e0 00 00 00
)
00 00 00 03
--> Number of entries in the vector
38 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 47 ef ff ff e0 00 00 00
--> 1.1754943508222875e-38, 0.0, 3.4028234663852886e+38 (8 bytes per entry)
Additional information (Original posting)
Serialization is not a trivial topic but there are many libraries out there, that can help you with that. In the end you have two options to choose from:
- Define your own serialization format
- Use an existing serialization format
- Binary
- Text based (e.g. JSON, XML)
Which one you choose depends highly on your needs and use cases. In general I would prefer established formats over self-brewed. Text-based formats are by nature less compact and need more space and therefore also bandwidth. This is something you should take into account when you decide for a format. On the other hand text-based/human-readable formats have the advantage of being easier to debug, as you can open them in a text editor. And there are many more factors you should consider.
Serialization works because you do not rely on machine dependent things. The only thing you have to take care of is that the serialized data is consistent and follows the defined format. So for the serialized data you know exactly how the byte order is defined, where specific data is stored and so on.
The idea is that the sender serializes the data, sends it over whatever channel is required, and the receiver deserializes the data again. In which format the data is stored on each of the both sides doesn't matter.
+--------------------------------+ +--------------------------------+
| Host A | | Host B |
| | | |
| | | |
| | | |
| +-------------------------+ | | +-------------------------+ |
| | Raw data | | | | Raw data | |
| |(Specific to plattfrom A)| | | |(Specific to plattfrom B)| |
| +-------------------------+ | | +-------------------------+ |
| | | | ^ |
| | serialize | | | deserialize |
| v | | | |
| +-----------------+ | transmit | +-----------------+ |
| | Serialized Data +----------------------------> Serialized Data | |
| +-----------------+ | | +-----------------+ |
| | | |
+--------------------------------+ +--------------------------------+