Extends C++ support for the nanopb and protobuf.
Project is designed to map structures generated by nanopb and C++ models for easy encoding/decode complicated types like variable-length strings, arrays, maps, oneof(union) messages, etc.
- Written to support C++ 11 standard.
- One-line call encode/decode for complicated messages.
- Reusable converters for inner messages.
- Template-based classes with static methods for converters.
All scalar types are defined in NanoPb::Type
namespace.
Base scalar types:
- Int32
- SInt32
- UInt32
- Fixed32
- SFixed32
- Float
- Bool
- String
- Bytes
64 bit scalar types, supported only if definition PB_WITHOUT_64BIT
was not set:
- Int64
- SInt64
- UInt64
- Fixed64
- SFixed64
- Double
-
TODO: describe
-
TODO: describe
-
TODO: describe
UnionMessageConverter
- Converter for union (oneof) messages. Derived fromMessageConverter
.
All scalar converters are derived from CallbackConverter
class.
Base scalar converters:
Int32Converter
SInt32Converter
UInt32Converter
Fixed32Converter
SFixed32Converter
FloatConverter
BoolConverter
StringConverter
BytesConverter
64 bit scalar types, supported only if definition PB_WITHOUT_64BIT
was not set:
Int64Converter
SInt64Converter
UInt64Converter
Fixed64Converter
SFixed64Converter
DoubleConverter
All container converters are derived from CallbackConverter
class.
ArrayConverter
- Array converter forstd::vector<xxx>
orstd::list<xxx>
.MapConverter
- Map with any type of the key and value.
- Use
add subdirectory()
orCPMAddPackage()
from CPM to add nanopb_cpp to your CMake project. - Set
NANOPB_VERSION
cmake variable to use custom nanopb version/git tag. - nanopb will be downloaded via CPM. Set
CPM_lib_nanopb_SOURCE
cmake variable to use your own nanopb location if you want to skip download. - Use
target_link_libraries(YOUR_TARGET nanopb_cpp)
to add dependency.
CPM example:
set(NANOPB_CPP_VERSION master)
CPMAddPackage(NAME lib_nanopb_cpp GITHUB_REPOSITORY nanopb/nanopb_cpp GIT_TAG ${NANOPB_CPP_VERSION})
NOTE: You can add DOWNLOAD_ONLY YES
to CPMAddPackage()
to prevent calling add_subdirectory()
. Project will be just downloaded in this case and you should add sources to your target manually.
- Install nanopb. Generate code from it.
- Add nanopb_cpp.cpp to your project sources.
PlatformIO package: https://registry.platformio.org/packages/libraries/nanopb/Nanopb_Cpp
- Use
#include nanopb_cpp.h
in your code. - Define C++
class/struct
for each protobuf message generated by nanopb. - Define converter for each local/protobuf structs, inherit from
MessageConverter
. - Define callback converters for callback fields, inherit from
CallbackConverter
. - Use other converters depending on your protobuf structures.
- See examples folder for the examples.
- See tests folder. (NOTE: copy constructors are disabled just for test reasons. You don't need to disable them actually.)
syntax = "proto3";
package PROTO;
message TestMessage {
string str = 1;
}
struct TestMessage {
std::string str;
TestMessage() = default;
TestMessage(const TestMessage&) = delete;
TestMessage(TestMessage&&) = default;
};
using namespace NanoPb::Converter;
class TestMessageConverter : public MessageConverter<
TestMessageConverter,
TestMessage,
PROTO_TestMessage,
&PROTO_TestMessage_msg>
{
public:
static ProtoType encoderInit(const LocalType& local) {
return ProtoType{
.str = StringConverter::encoderCallbackInit(local.str)
};
}
static ProtoType decoderInit(LocalType& local){
return ProtoType{
.str = StringConverter::decoderCallbackInit(local.str)
};
}
static bool decoderApply(const ProtoType& proto, LocalType& local){
return true;
}
};
const TestMessage original(
{"My super string"}
);
// Define output stream.
NanoPb::StringOutputStream outputStream;
// Encode
if (!NanoPb::encode<TestMessageConverter>(outputStream, original)){
// encode error
}
// Define input stream
auto inputStream = NanoPb::StringInputStream(outputStream.release());
TestMessage decoded;
/// Decode message
if (!NanoPb::decode<TestMessageConverter>(inputStream, decoded)){
// decode error
}
- All C++ classes should have default constructor
- All C++ classes should have copy constructor or move constructor
- ArrayConverter can't work with
std::vector<bool>
, because it has specific implementation which is not compatible with standard behavior.