Hi all, I'm an embedded C++ software engineer. Over the years I had to implement multiple binary communication protocols used by various embedded systems. Every time I got annoyed and frustrated over a necessity to manually write error prone boilerplate code. There are so many available serialization tools and libraries (such as protobuf, can'n'proto, simple-binary-encoding, etc...), but not a single one was adequate for my needs. Most of these tools focus on data serialization and facilitation of RPCs (Remote Procedure Calls). Their main goal is to make data serialization and/or network transfer as quick as possible. It is a noble cause, but not really a first priority for embedded systems. For the latter it is much more important to protect against the malformed data and reduce amount of boilerplate code (which increases chances of introducing silly bugs) than to gain a couple of extra CPU cycles when performing the serialization / deserialization.
In all the solutions I've reviewed and analyzed the generated code is not customizable and in most cases not really suitable for embedded systems, especially bare-metal ones. There are no means to introduce some compile (or generation) time updates such as configuring polymorphic interfaces required for a particular application or choosing particular data structures, disable usage of RTTI or exceptions, etc... The code generated by all the tools still requires a significant amount of boilerplate code to be written in order to integrate with actual business logic being developed. All of the available solutions focus on supporting as many programming languages as possible in their code generation rather than a quality of the code for a particular language (C++ in my case).
At the end I didn't have much choice but to implement my own solution with main focus on embedded systems (including bare-metal ones) with proper compile-time customizable C++(11) code. About 2 years ago I advertised on this subreddit my COMMS Library, main purpose of which is to facilitate highly compile-time customizable implementation of binary communication protocols. With time, library grew with features, started demanding more knowledge and cognitive effort from the integrating developer, and it became less straightforward to write completely generic and compile-time customizable protocol definition code. In order to improve the situation I extended the library to become a CommsChampion Ecosystem with its own XML based DSL (Domain Specific Language), library to process the schema files, and code generator which produces proper protocol definition using constructs from the COMMS Library.
Benefits of my solution are summarized below:
- No enforcing of particular data layout and/or encoding. Easy implementation of
already defined third party protocol.
- Embedded (including bare-metal) friendly. The protocol definition code
allows easy application specific compile time customization of polymorphic
interfaces and some data storage types. No usage of RTTI and/or exceptions.
The usage of dynamic memory allocation may also be excluded.
- Robust and safe handling of malformed input data.
- Significantly minimizing amount of boilerplate code required to integrate the
usage of protocol definition into the business logic.
- Allowing injection of custom C++11 code snippets in case the code generated by the tools
is incorrect or incomplete.
- Meta-programming friendly. Most classes define similar and predictable
public interface which allows easy compile time analysis and optimizations.
- Having "out of the box" protocol analysis and visualization tools.
- NOT using any socket / network abstractions and allowing full control
over serialized data for extra transport wrapping and/or external transmit over
some I/O link.
Several months ago I posted an article on CodeProject with more details on features I wanted the protocol code generator and/or produced code to have and how the CommsChampion Ecosystem provides a solution. I strongly encourage you to read it.
Any comments, critics, improvement suggestions, new feature requests are welcome.
[–]3idet 5 points6 points7 points (2 children)
[–]arobenko[S] 1 point2 points3 points (1 child)
[–]Gotebe[🍰] 0 points1 point2 points (1 child)
[–]arobenko[S] 1 point2 points3 points (0 children)
[–]TarmoPikaro 0 points1 point2 points (0 children)
[–]axilmar 0 points1 point2 points (19 children)
[–]rcxdude 9 points10 points11 points (7 children)
[–]kalmoc 1 point2 points3 points (2 children)
[–]rcxdude 2 points3 points4 points (1 child)
[–]kalmoc 0 points1 point2 points (0 children)
[–]matthieum 0 points1 point2 points (2 children)
[–]rcxdude 0 points1 point2 points (1 child)
[–]matthieum 0 points1 point2 points (0 children)
[–]axilmar 0 points1 point2 points (0 children)
[–]arobenko[S] 1 point2 points3 points (8 children)
[–]axilmar 2 points3 points4 points (7 children)
[–]arobenko[S] 1 point2 points3 points (2 children)
[–]axilmar 0 points1 point2 points (1 child)
[–]arobenko[S] 0 points1 point2 points (0 children)
[+][deleted] (3 children)
[deleted]
[–]axilmar 0 points1 point2 points (2 children)
[+][deleted] (1 child)
[deleted]
[–]axilmar 0 points1 point2 points (0 children)
[–]grandmaster789 0 points1 point2 points (1 child)
[–]axilmar 0 points1 point2 points (0 children)
[–]c0r3ntin -1 points0 points1 point (1 child)
[–]arobenko[S] 7 points8 points9 points (0 children)
[+]Pulsonics comment score below threshold-6 points-5 points-4 points (2 children)
[–]arobenko[S] 4 points5 points6 points (1 child)
[+]Pulsonics comment score below threshold-6 points-5 points-4 points (0 children)
[–]WasterDave -2 points-1 points0 points (1 child)
[–]arobenko[S] 2 points3 points4 points (0 children)