One libraray about cpp object serilization

Discuss one exmaple library about cpp serilization and unserilization

Unlike the golang or java that provide the official serilization and decirilization libraray, we may need to use the third part library for the object serilization and decirilization. One example library that we want to introduce is this library: cereal (https://github.com/USCiLab/cereal). There are detailed documents about how to use this library. We just put an small example here to show some ideas about this library.

Just like many convenient cpp tool libraray, we only need to include the header file in order to use the cereal.

this is an exmaple code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <cereal/archives/binary.hpp>
#include <cereal/archives/xml.hpp>
#include <cereal/types/vector.hpp>
#include <iostream>
#include <sstream>
#include <vector>

class Object {
public:
Object(){};
Object(unsigned width, unsigned height, unsigned depth, double z_offset,
float range = 1.2, unsigned nblocks = 1)
: m_width(width),
m_height(height),
m_depth(depth + 1),
m_extents(6),
m_origin(3),
m_data(width * height * (depth + 1)),
m_z_offset(z_offset),
m_range(range),
m_nblocks(nblocks) {
// initilization
}

Object(const Object&) = default;
Object(Object&&) = default;
Object& operator=(const Object&) = default;
Object& operator=(Object&&) = default;
~Object() = default;

bool compare(Object& other) {
if (other.m_width != m_width || other.m_height != m_height ||
other.m_depth != m_depth) {
std::cout << "unequal part1" << std::endl;
return false;
}
if (other.m_z_offset != m_z_offset || other.m_range != m_range ||
other.m_nblocks != m_nblocks) {
std::cout << "unequal part2" << std::endl;
return false;
}
if (other.m_extents.size() != m_extents.size() ||
other.m_origin.size() != m_origin.size() ||
other.m_data.size() != m_data.size()) {
std::cout << "unequal part3" << std::endl;
return false;
}
for (int i = 0; i < m_extents.size(); i++) {
if (other.m_extents[i] != m_extents[i]) {
std::cout << "unequal m_extents" << std::endl;
return false;
}
}
for (int i = 0; i < m_origin.size(); i++) {
if (other.m_origin[i] != m_origin[i]) {
std::cout << "unequal m_origin" << std::endl;
return false;
}
}
for (int i = 0; i < m_data.size(); i++) {
if (other.m_data[i] != m_data[i]) {
std::cout << "unequal m_data" << std::endl;
return false;
}
}
return true;
}

void caculateSize() {
size_t stackVar;
stackVar = sizeof(m_width) + sizeof(m_height) + sizeof(m_depth) +
sizeof(m_extents) + sizeof(m_origin) + sizeof(m_data) +
sizeof(m_z_offset) + sizeof(m_range) + sizeof(m_nblocks);
std::cout << "major ariables";
std::cout << " m_width " << sizeof(m_width) << ",";
std::cout << " m_extents " << sizeof(m_extents) << ",";
std::cout << " m_origin " << sizeof(m_origin) << ",";
std::cout << std::endl;

std::cout << " stackVar " << stackVar << std::endl;

size_t heapVar = sizeof(int) * m_extents.size() +
sizeof(double) * m_origin.size() +
sizeof(int) * m_data.size();

std::cout << " heapVar " << heapVar << std::endl;
}

// binary output based on cereal
// https://uscilab.github.io/cereal/serialization_archives.html
// the function should be public one!
template <typename A>
void serialize(A& ar) {
ar& m_width;
ar& m_height;
ar& m_depth;
ar& m_extents;
ar& m_origin;
ar& m_data;
ar& m_z_offset;
ar& m_range;
ar& m_nblocks;
}

private:
size_t m_width;
size_t m_height;
size_t m_depth;
std::vector<int> m_extents;
std::vector<double> m_origin;
std::vector<int> m_data;
unsigned m_z_offset;
float m_range;
unsigned m_nblocks;
};

int main() {
static unsigned LEN = 10;
Object ob(LEN, LEN, LEN, 1, 1.2, 5);

std::stringstream ss; // any stream can be used

cereal::BinaryOutputArchive oarchive(ss); // Create an output archive

oarchive(ob); // Write the data to the archive

// oarchive.saveBinaryValue(mb, sizeof(mb), "mb");

std::string bufferedstr = ss.str();

std::cout << "serilized size " << bufferedstr.size() << " original size "
<< sizeof(ob);

// deserialize
std::stringstream is(bufferedstr);

cereal::BinaryInputArchive archive_in(is);
Object mbnew;
archive_in(mbnew);

bool ifequal = ob.compare(mbnew);
std::cout << " ifequal " << ifequal << std::endl;

mbnew.caculateSize();

return 0;
}

Several interesting things

you may need to use stringstream to transfer the marshaled data into a string

you also need to add an public template function in the defination of the object in order to use the cereal

When we check the size of the object

1
2
3
4
serilized size 4508 original size 112 ifequal 1
major ariables m_width 8, m_extents 24, m_origin 24,
stackVar 108
heapVar 4448

You could see that the serilized size contains both the stack variable and the heap variable. The sizeof only caculate the stack varaible, that is why the size of the object is 112

References

https://uscilab.github.io/cereal/quickstart.html

https://github.com/wangzhezhe/5MCST/tree/master/unclassified/ceralexample

推荐文章