I am working on an embedded C++ project. I am dealing with complex and dynamic objects with lots of objects pointing to one another. I need to store and recall these objects to non-volatile memory. In the past I used structures for data and could easily turn them into byte streams using tricks like unions. How do I do this with objects?
-
3\$\begingroup\$ Keep in mind that there are a limited number of writes to non-volatile memory, so if you are doing this frequently you could wear out the memory. Other than that this seems like a C++ question in general and not an embedded question specifically. \$\endgroup\$– Elliot AldersonCommented Sep 9, 2021 at 15:10
-
\$\begingroup\$ Elliot Alderson has an important point. As for how to save objects, you need to take address in memory where the object begins and its size in bytes and manually copy the from RAM (or wherever the object is sitting) byte by byte with a loop. You may want to google things like "memory pointer" "object in memory" and similar things (if you're not familiar yet, that is). It's a little overwhelming at first (actually, it's pretty brain-breaking) \$\endgroup\$– IlyaCommented Sep 9, 2021 at 15:20
-
1\$\begingroup\$ The problem is converting pointers to other objects to something that is not a pointer but some sort of other reference so that when you load objects to memory again and they are in different memory addresses or in different order you can change them back to memory addresses. If you can do this using C++ on a linux/windows/macos/whatever using files as storage then you can do it in embedded C++ using flash. The embedded context is irrelevant. \$\endgroup\$– JustmeCommented Sep 9, 2021 at 15:39
-
3\$\begingroup\$ The keyword you are looking for is "serialization" and it is not trivial. \$\endgroup\$– Criticizing Israel not allowedCommented Sep 9, 2021 at 16:10
-
4\$\begingroup\$ I’m voting to close this question because it's a pure software question that belongs on StackOverflow. \$\endgroup\$– Dave TweedCommented Sep 9, 2021 at 18:55
2 Answers
I would provide each class with a member function serialize
, which fills up an internal static uint8_t
buffer with the variables that need to be stored, then returns a const uint8_t*
and a size to the caller, who can then pass that along to the NVM driver.
If you have complex inheritance you can let each inherited class append its own data at the end of this buffer.
Similarly, you might want a deserialize
routine initialized with a pointer to NVM and a size. This might be a constructor even.
Also keep in mind that NVM variables that are changed in run-time need to be accessed through volatile
qualified variables/pointers.
-
\$\begingroup\$ You can make serialize and deserialize static functions so that they can create and return a pointer to a new object. For embedded make serialize work like snprintf, which is copyless. \$\endgroup\$– Jeroen3Commented Sep 10, 2021 at 9:19
-
1\$\begingroup\$ @Jeroen3 This design assumes a microcontroller system with limited memory and no dynamic allocation. The point is to not allocate big buffers all over the place. \$\endgroup\$– LundinCommented Sep 10, 2021 at 9:31
-
\$\begingroup\$ it's fine to use
new
if you're only going to make the object once. \$\endgroup\$– Jeroen3Commented Sep 10, 2021 at 12:58
This process is called "Object serialization". If you have a powerful MCU, you might be able to use an off-the-shelf library to do it.
If not, it shouldn't be too hard for you to write a few functions and methods to accomplish this. Your objects contain data in the form of variables, so all you need to do is read the data in each variable and store it in NVM in an organized way.
When you start back up, you read the data from NVM and use it to create objects.
Pointers would be hard to store this way, but you can do things like create an id for each object, and store the ID of the object you want to point to, instead of the actual memory address.
Dynamic memory allocation also complicates this a bit, but the same basic strategy applies.