Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Nanopb: Migration from older versions

This document details all the breaking changes that have been made to nanopb since its initial release. For each change, the rationale and required modifications of user applications are explained. Also any error indications are included, in order to make it easier to find this document.

Nanopb-1.0.0 (2025-xx-xx)

API version compatibility defines

Rationale: Several API changes have been made in nanopb-1.0.0. To make porting old code easier, a define controls whether compatibility wrappers are defined in the headers.

Changes: You can optionally define PB_API_VERSION to the nanopb version that compatibility is aimed for. Use PB_API_VERSION_v0_4 for nanopb-0.4 compatibility, and PB_API_VERSION_LATEST or PB_API_VERSION_v1_0 for new code.

Required actions: Define PB_API_VERSION or use tools/nanopb_api_updater.py to update old code.

Directory layout reorganized

Rationale: Moving nanopb source files to a subdirectory makes build system integration easier. Having headers under folder nanopb avoids namespace conflicts when including files.

Changes: Source files pb_decode.c etc. are now under src/. Header files pb_decode.h etc. are now under include/nanopb. Internally #include "nanopb/pb.h" is used to include nanopb headers.

Required actions: Change compiler include paths as needed. User code can continue to use #include <pb.h> as before if include/nanopb is added to the include path.

Streams renamed to context

Rationale: Previously streams only handled reading/writing. This has been replaced with a ctx argument that can contain e.g. allocator information. The ctx pointer is always passed as-is to callbacks, only the fields inside are modified during processing. Previously the callbacks were given varying stream pointers when substreams were processed.

Changes: pb_istream_t is now pb_decode_ctx_t and pb_ostream_t is pb_encode_ctx_t.

Required actions: Rename types or define PB_API_VERSION as PB_API_VERSION_v0_4. tools/nanopb_api_updater.py can rename types automatically.

Stream/context structure members renamed

Rationale: To distinguish it from the field callback, ctx->callback is renamed to ctx->stream_callback and its state variable to stream_callback_state.

Required actions: In custom stream callbacks, change state to stream_callback_state. For initializing pb_decode_ctx_t and pb_encode_ctx_t, use the new function such as pb_init_encode_ctx_for_callback().

Stream callback function signature changed

Rationale: Previously input stream callback only reported success/failure, and the reporting of end-of-stream condition was complicated. Now input stream callback returns the number of bytes successfully read, which simplifies EOF handling. For output stream callbacks the only difference is used of pb_size_t instead of size_t in argument.

Required actions: Update any custom input stream callbacks to follow the specification given in pb_decode.h comments.

pb_field_t is now pb_field_iter_t in field callback signature

Rationale: Back in 0.4.0, pb_field_t was renamed into pb_field_iter_t to reflect the iterator routines in pb_common.h that were introduced to access it. A typedef for pb_field_t was provided for backwards compatibility.

Changes: pb_field_t typedef is now only defined if PB_API_VERSION is defined. In particular, this affects field callbacks in user code.

Required actions: Rename type to pb_field_iter_t or define PB_API_VERSION as PB_API_VERSION_v0_4. tools/nanopb_api_updater.py can rename types automatically.

Initialization of encoding sizing streams changed

Changes: Previously a pb_ostream_t initialized to zero values, such as with = {}, acted as a sizing stream. Now the flags and max_size have to be set.

Required actions: Use pb_init_encode_ctx_sizing() to initialize the encoding context before a size calculating operation.

Built-in support for null-terminated streams is removed

Rationale: Previously nanopb implemented an option to terminate decoding on a null byte. This is a non-standard feature which does not exist in other protobuf libraries. Retaining it in the core would expand size for a fairly rarely used feature.

Required actions: Null-terminated streams can now be handled using a custom stream callback. See tests/framing/ for an example.

All features are enabled by default

Rationale: Previously some features were disabled with PB_NO_xxxx macro, while others were enabled with PB_ENABLE_xxxx macros. The disabled features got poorer compilation test coverage, and the ABI compatibility depended on what was enabled.

Changes: All supported features are enabled by default. The exception is platform-specific features and special compatibility settings. In particular, malloc support and utf8-validation are now enabled by default. The macros are now always defined as either 0 or 1, and instead of #ifdef, #if should be used. New setting PB_MINIMAL makes all features default to disabled.

Required actions: Check required features, and define e.g. PB_NO_MALLOC or PB_NO_VALIDATE_UTF8 to 1 if preferred. If user code uses #ifdef on the PB_ feature defines, convert it to #if. The nanopb_api_updater.py script can perform this automatically in most cases.

Fields keep their .proto file order by default

Rationale: For technical reasons, nanopb-0.3.x and earlier required fields to be sorted by their tag number in the generated C struct. Nanopb-0.4.x allowed using the definition order from .proto file, but kept the old default sorting.

Changes: Default value of generator setting sort_by_tag is now false. Fields in generated C structure are in the order they are listed in the .proto file.

Required actions: If custom initializers or other code relies on the order of fields, the option sort_by_tag = true can be used to restore old behavior.

Remove custom extension field callback support

Rationale: Previously extension fields used extra pb_extension_type_t indirection level. This was rarely used, not well-tested and is overlapping in functionality with the new context-based callback mechanism.

Changes: Only automatically generated extension types are supported.

Required actions: If custom extension field callback function was used, it can be converted to a context field callback. Any unknown fields are passed to the context field callback. See tests/extra_fields/decode_extra_fields.c.

Structure size check in functions

Rationale: A common mistake has been a mismatch between the fields and struct parameters given to encoding and decoding functions. This can result in access out of bounds of the structure, or just garbage data. Same problem can occur if compilation options differ between the .pb.c and user code files.

Changes: The functions that take a pb_msgdesc_t *fields arguments have been wrapped into macros, which pass sizeof(struct) as the last argument. The function itself then compares the argument to the size defined in the fields, and returns error if they differ.

Required actions: Most code works without changes. Problems occur if the type of the structure is not known at the callsite and void* is used instead. To resolve this, call the underlying function (e.g. pb_decode_s) with the size argument set to 0.

Error indications: “invalid application of ‘sizeof’ to a void type” or “you cannot dereference an operand of type ‘void’”

Change layout of pointer-type bytes fields

Rationale: Previously pointer-type bytes fields stored the length of the value in front of the data. This made it unsuitable for pointing to a block of raw bytes without length prefix.

Changes: Now instead of a direct pointer, there is pb_bytes_t structure. This contains the size and a pointer to raw byte array.

Error indications: Type mismatch compilation errors involving pb_bytes_t.

Changes to field iterator utility functions

Rationale: The functions defined in pb_common.h are rarely used in user code. Their APIs have seen small changes to better accommodate other changes in the codebase.

Changes: pb_field_iter_find() takes a third argument, which can be given as NULL.

Changed size_t to pb_size_t in structures

Rationale: Previously stream structures used platform size_t for the lengths. In practice the lengths will not be longer than pb_size_t can fit. Using pb_size_t everywhere avoids unnecessary casts and bound checks. The size_t is still retained in function call APIs that interface with system, such as read/write/realloc. The data type of pb_size_t is always smaller or equal to size_t.

Required actions: In some cases SIZE_MAX in user code may need to be replaced with PB_SIZE_MAX to silence compiler warnings.

Reserved identifiers in generated headers

Rationale: Previously nanopb generator made definitions such as typedef struct _MyMessage { ... } MyMessage; and _MyEnum_MAX. Identifiers beginning with underscore are reserved in C.

Changes: Generator now uses format typedef struct MyMessage { ... } MyMessage; and ENUM_MyEnum_MAX.

Required actions: If forward declarations or enum defines are used in user code, update the identifier names.

Error indications: _MyEnum_MIN undeclared

Default fallback type for fields without max size

Rationale: Previously string/bytes/array fields without a maximum size or count option were converted into pb_callback_t. This was often confusing to new users of the library, and led to using callbacks even when the simpler maximum size define would have been easier.

Changes: Default fallback type is now FT_STATIC with compile-time defines such as MyMessage_myfield_max_size. These can then be overridden using compiler options or (preferred) using generator options. In either case, it should make the maximum size options more discoverable.

Required actions: If you want fields to remain callback type, either add (nanopb).type = FT_CALLBACK on the single field, or (nanopb).fallback_type = FT_CALLBACK globally.

Proto3 singular submessages are unconditionally encoded

Rationale: Since nanopb-0.4.0, proto3 submessages have had a separate has_ field, consistent with behavior of other protobuf libraries. This can be omitted with generator option proto3_singular_msgs. Previously submessage was then recursively checked for non-zero values.

Changes: To simplify code, singular submessages are now unconditionally encoded as zero-length value. This decodes to the same result, but takes 2 bytes more in the encoded representation.

Remove Python 2 support

Rationale: Python 2 interpreter was deprecated in 2020. For backward compatibility, nanopb has retained support for running the generator with Python 2 for the 0.4.x series. That has required several tricks that complicate the codebase.

Changes: Removed Python 2 support files and code hacks needed to make it work.

Required actions: Upgrade to Python 3 and ensure python-protobuf is installed.

Nanopb-0.4.9 (2024-09-19)

CMake rules now default to grpcio_tools protoc

Rationale: Previously CMake rules primarily looked for protoc in system path. This was often an outdated version installed from package manager, and not necessarily compatible with python-protobuf version installed from pip.

Changes: CMake rules now default to using generator/protoc, which in turn uses grpc_tools Python package if available. If it is not available, system path is searched for protoc.

Required actions: For most users, no actions are needed. In case of version incompatibilities, pip install --user --upgrade grpcio-tools protobuf is recommended. If needed, PROTOBUF_PROTOC_EXECUTABLE can be set to override the default.

Error indications: Failed to import generator/proto/nanopb_pb2.py if versions of protoc selected by CMake is different than installed python-protobuf.

Use uint8_t for pb_byte_t when UINT8_MAX is defined

Rationale: Previously pb_byte_t was always defined as uint8_least_t. This could be annoying on some platforms without this define, or when some compiles might warn on conversion from uint8_t. However not all platforms support uint8_t sized access.

Changes: The stdint.h header will define UINT8_MAX exactly if uint8_t is available. Use it to select which type to typedef.

Required actions: Usually none. If any compiler warnings are generated, they can either be fixed or PB_BYTE_T_OVERRIDE can be defined to uint_least8_t to restore old behavior.

Error indications: Implicit conversion from uint_least8_t to uint8_t.

Migrate to bzlmod

Rationale: Due to the shortcomings of the WORKSPACE system, Bzlmod is going to replace the legacy WORKSPACE system in future Bazel releases. Therefore, nanopb has been migrated to use bzlmod to better support newer bazel versions.

Changes

  • upgrade bazel deps
    • bazel_skylib: 1.7.1
    • rules_python: 0.34.0
    • rules_proto: 6.0.2
    • protobuf: 24.4
    • rules_proto_grpc: 5.0.0
  • Start using bzlmod (MODULE.bazel)

Required actions: bazel build using WORKSPACE has been deprecated. To use bzlmod, adding below content to your MODULE.bazel

bazel_dep(name = "nanopb", version = "0.4.9")
git_override(
    module_name = "nanopb",
    remote = "https://github.com/nanopb/nanopb.git",
    commit = "<commit>",
)

noted that the name of the module has been changed to nanopb, to better fit the convention of bzlmod. If the old name com_github_nanopb_nanopb is preferred, can add repo_name parameter to indicate the repo name.

bazel_dep(name = "nanopb", version = "0.4.9", repo_name="com_github_nanopb_nanopb")

Separate enum_intsize setting

Rationale: Nanopb-0.4.7 extended int_size option to affect enums. This is only supported by C++11 and C23 compilers. The generation used #ifdef to limit size option to use on C++ compilers. This caused binary incompatibility when project mixed C and C++ files.

Changes: enum_intsize is now a separate option, and does not use #ifdef. If compiler does not support the setting, compilation will fail.

Required actions: If using the recently introduced int_size option on enums, update to use enum_intsize instead.

Error indications: Enum integer sizes use defaults as the old setting is ignored.

Nanopb-0.4.8 (2023-11-11)

Fix naming conflicts with CMake installation

Rationale: Previously CMakeLists.txt installed nanopb Python module under name proto and include file directly as /usr/include/pb.h. These names have potential to conflict with other libraries.

Changes: Python module is installed as nanopb and include files under /usr/include/nanopb.

Required actions: Only affects users who install nanopb using the cmake build system. Does not affect use of FindNanopb.cmake. Calling nanopb generator should work as before. Include path may need adjustment if not using nanopb-targets.cmake to determine it.

Error indications: Include file pb.h not found when compiling against a system-wide installation done with CMake.

Nanopb-0.4.7 (2022-12-11)

Add int_size option to enum fields

This option was separated to enum_intsize in nanopb-0.4.9. This migration notice has been updated to match.

Rationale: The packed_enum option does not work with MSVC due to #pragma pack not supporting enums with MSVC. To workaround this, enum sizes can be specified with the new int_size option. Note that this is only supported when generating C++.

Changes: The int_size enum_intsize option can be specified for enums.

Required actions: Any users concerned about the size of the generated C++ enums and are setting the int_size of enums via a wildcard (e.g. MyMessage.* int_size=IS_8) will need to instead set the int_size option for individual fields.

Error indications: The size of generated C++ enums has changed.

Updated include path order in FindNanopb.cmake

Changes: The include path passed to protoc by the CMake rules was updated.

Required actions: No changes needed for most users. In some specific cases it could change the directory hierarchy generated by protoc. More details in pull request #822.

Error indications: Generated .pb.c or .pb.h file not found when building with CMake rules.

Nanopb-0.4.6 (2022-05-30)

NANOPB_VERSION define is now a string

Changes: To ease NANOPB_VERSION macro usage, the value is directly a string.

Required actions: Most nanopb users probably never used that macro. If so, you certainly use the # preprocessor to convert it as string. You, now, only have to call it directly, like this for example: strcpy(myvar, NANOPB_VERSION);

FindNanopb.cmake now requires protoc 3.6.0 or newer by default

Changes: The default options passing method now uses --plugin-opt which is supported by protoc 3.6.0 and newer (released in 2018).

Required actions: Update protoc if needed, or alternatively install grpcio-tools package from pip. If neither is possible, the NANOPB_PROTOC_OLDER_THAN_3_6_0 cmake option can be used to restore the old style option passing. Note that it has problems with special characters such as :.

Error indications:protoc: Unknown flag: --nanopb_opt

pb.h uses C11 _Static_assert keyword by default

Rationale: The nanopb generated headers use static assertions to catch errors at compile time. There are several mechanisms to implement this. The most widely supported is C11 _Static_assert keyword. Previously the code used negative size array definition trick, which is supported already in C99 but does not work with every compiler and can produce confusing error messages.

Changes: Now _Static_assert is used by default.

Required actions: If the keyword is not recognized, set the compiler to C11 standard mode if available. If it is not available, define either PB_C99_STATIC_ASSERT or PB_NO_STATIC_ASSERT in pb.h or on compiler command line.

Error indications: Undefined identifier _Static_assert

Nanopb-0.4.4 (2020-11-25)

Remove outdated generator/nanopb/options.proto

Changes: Back in 2018, it was considered in pull request #241 to move nanopb generator options to a separate namespace. For this reason, a transitional file was added. It was later abandoned and is now removed to avoid confusion.

Required actions: Most nanopb users probably never used that transitional file at all. If your .proto files import it, change to using generator/proto/nanopb.proto.

Error indications: Errors about missing file options.proto when running the generator.

Nanopb-0.4.3 (2020-09-21)

pb_msgdesc_t struct has new fields

Changes: New fields required_field_count and largest_tag were added to pb_msgdesc_t and existing fields were reordered.

Required actions: All .pb.c files must be recompiled. Regeneration is not needed.

Error indications: Messages may fail to encode or decode, or the code can crash inside load_descriptor_values() in pb_common.c.

Nanopb-0.4.2 (2020-06-23)

Generator now uses Python 3 by default

Rationale: Previously nanopb-generator.py had hashbang of #!/usr/bin/env python, which would execute with Python 2 on most systems. Python 2 is now deprecated and many libraries are dropping support for it, which makes installing dependencies difficult. While nanopb_generator.py has worked with Python 3 for years now, and overriding the python version was possible with virtualenv, that was an extra complication.

Changes: Hashbang now uses #!/usr/bin/env python3. New file nanopb_generator.py2 can be used to run with Python 2, if necessary.

Required actions: If possible, just verify Python 3 is installed and necessary dependencies are installed for it. For example pip3 install protobuf grpcio-tools should take care of it. If this is not possible, call nanopb_generator.py2 from your build scripts instead.

Error indications: python3: command not found if Python 3 is not installed. Could not import the Google protobuf Python libraries if dependencies are only installed for Python 2.

Nanopb-0.4.0 (2019-12-20)

New field descriptor format

Rationale: Previously information about struct fields was stored as an array of pb_field_t structures. This was a straightforward method, but required allocating space for e.g. submessage type and array size for all fields, even though most fields are not submessages nor arrays.

Changes: Now field information is encoded more efficiently in uint32_t array in a variable-length format. Old pb_field_t structure has been removed and it is now a typedef for pb_field_iter_t. This retains compatibility with most old callback definitions. The field definitions in .pb.h files are now of type pb_msgdesc_t.

Required actions: If your own code accesses the low-level field information in pb_field_t, it must be modified to do so only through the functions declared in pb_common.h.

Error indications: incompatible pointer type errors relating to pb_field_t

Changes to generator default options

Rationale: Previously nanopb_generator added a timestamp header to generated files and used only basename of files in #include directives. This is different than what the protoc C++ backend does.

Changes: Now default options are --no-timestamp and --no-strip-path.

Required actions: If old behaviour is desired, add --timestamp and --strip-path options to nanopb_generator.py or on protoc command line as --nanopb_out=--timestamp,--strip-path:outdir.

Error indications: Compiler error: cannot find include file mymessage.pb.h when compiling mymessage.pb.c.

Removal of bundled plugin.proto

Rationale: Google’s Python protobuf library, which is used in nanopb generator, has included plugin_pb2 with it since version 3.1.0. It is not necessary to bundle it with nanopb anymore.

Required actions: Update python-protobuf to version 3.1.0 or newer.

Error indications: ImportError: No module named compiler.plugin_pb2

.options file is now always case-sensitive

Rationale: Previously field names in .options file were case-sensitive on Linux and case-insensitive on Windows. This was by accident. Because .proto files are case-sensitive, .options files should be too.

Changes: Now field names in .options are always case-sensitive, and matched by fnmatchcase() instead of fnmatch().

Required actions: If field names in .options are not capitalized the same as in .proto, they must be updated.

CHAR_BIT define is now needed

Rationale: To check whether the platform has 8-bit or larger chars, the C standard CHAR_BIT macro is needed.

Changes: pb.h now includes limits.h for this macro.

Required actions: If your platform doesn’t have limits.h available, you can define the macro in pb_syshdr.h. There is an example in extra directory.

Error indications: "Cannot find include file <limits.h>." or "Undefined identifier: CHAR_BIT."

Strings must now always be null-terminated

Rationale: Previously pb_encode() would accept non-terminated strings and assume that they are the full length of the defined array. However, pb_decode() would reject such messages because null terminator wouldn’t fit in the array.

Changes: pb_encode() will now return an error if null terminator is missing. Maximum encoded message size calculation is changed accordingly so that at most max_size-1 strings are assumed. New field option max_length can be used to define the maximum string length, instead of the array size.

Required actions: If your strings were previously filling the whole allocated array, increase the size of the field by 1.

Error indications: pb_encode() returns error unterminated string.

Removal of per-field default value constants

Rationale: Previously nanopb declared a fieldname_default constant variable for each field with a default value, and used these internally to initialize messages. This however used unnecessarily large amount of storage for the values. The variables were mostly for internal usage, but were available in the header file.

Changes: Default values are now stored as an encoded protobuf message.

Required actions: If your code previously used default constants, it will have to be adapted to take the default value in some other way, such as by defining static const MyMessage msg_default = MyMessage_init_default; and accessing msg_default.fieldname.

Error indications: Compiler error about fieldname_default being undeclared.

Zero tag in message now raises error by default

Rationale: Previously nanopb has allowed messages to be terminated by a null byte, which is read as zero tag value. Most other protobuf implementations don’t support this, so it is not very useful feature. It has also been noted that this can complicate debugging issues with corrupted messages.

Changes: pb_decode() now gives error when it encounters zero tag value. A new function pb_decode_ex() supports flag PB_DECODE_NULLTERMINATED that supports decoding null terminated messages.

Required actions: If application uses null termination for messages, switch it to use pb_decode_ex() and pb_encode_ex(). If compatibility with 0.3.9.x is needed, there are also pb_decode_nullterminated() and pb_encode_nullterminated() macros, which work both in 0.4.0 and 0.3.9.

Error indications: Error message from pb_decode(): zero_tag.

Submessages now have has_field in proto3 mode

Rationale: Previously nanopb considered proto3 submessages as present only when their contents was non-zero. Most other protobuf libraries allow explicit null state for submessages.

Changes: Submessages now have separate has_field in proto3 mode also.

Required actions: When using submessages in proto3 mode, user code must now set mymsg.has_submsg = true for each submessage that is present. Alternatively, the field option proto3_singular_msgs can be used to restore the old behavior.

Error indications: Submessages do not get encoded.

PB_OLD_CALLBACK_STYLE option has been removed

Rationale: Back in 2013, function signature for callbacks was changed. The PB_OLD_CALLBACK_STYLE option allowed compatibility with old code, but complicated code and testing because of the different options.

Changes: PB_OLD_CALLBACK_STYLE option no-longer has any effect.

Required actions: If PB_OLD_CALLBACK_STYLE option was in use previously, function signatures must be updated to use double pointers (void** and void * const *).

Error indications: Assignment from incompatible pointer type.

protoc insertion points are no longer included by default

Rationale: Protoc allows including comments in form @@protoc_insertion_point to identify locations for other plugins to insert their own extra content. Previously these were included by default, but they clutter the generated files and are rarely used.

Changes: Insertion points are now included only when --protoc-insertion-points option is passed to the generator.

Nanopb-0.3.9.4, 0.4.0 (2019-10-13)

Fix generation of min/max defines for enum types

Rationale: Nanopb generator makes #defines for enum minimum and maximum value. Previously these defines incorrectly had the first and last enum value, instead of the actual minimum and maximum. (issue #405)

Changes: Minimum define now always has the smallest value, and maximum define always has the largest value.

Required actions: If these defines are used and enum values in .proto file are not defined in ascending order, user code behaviour may change. Check that user code doesn't expect the old, incorrect first/last behaviour.

Rationale: In C99, bool variables are not allowed to have other values than true and false. Compilers use this fact in optimization, and constructs like int foo = msg.has_field ? 100 : 0; will give unexpected results otherwise. Previously nanopb didn't enforce that decoded bool fields had valid values.

Changes: Bool fields are now handled separately as PB_LTYPE_BOOL. The LTYPE descriptor numbers for other field types were renumbered.

Required actions: Source code files must be recompiled, but regenerating .pb.h/.pb.c files from .proto is not required. If user code directly uses the nanopb internal field representation (search for PB_LTYPE_VARINT in source), it may need updating.

Nanopb-0.3.9.1, 0.4.0 (2018-04-14)

Fix handling of string and bytes default values

Rationale: Previously nanopb didn’t properly decode special character escapes like \200 emitted by protoc. This caused these escapes to end up verbatim in the default values in .pb.c file.

Changes: Escapes are now decoded, and e.g. \200 or \x80 results in {0x80} for bytes field and "\x80" for string field.

Required actions: If code has previously relied on \ in default value being passed through verbatim, it must now be changed to \\.

Nanopb-0.3.8 (2017-03-05)

Fully drain substreams before closing

Rationale: If the substream functions were called directly and the caller did not completely empty the substring before closing it, the parent stream would be put into an incorrect state.

Changes: pb_close_string_substream can now error and returns a boolean.

Required actions: Add error checking onto any call to pb_close_string_substream.

Change oneof format in .pb.c files

Rationale: Previously two oneofs in a single message would be erroneously handled as part of the same union.

Changes: Oneofs fields now use special PB_DATAOFFSET_UNION offset type in generated .pb.c files to distinguish whether they are the first or following field inside an union.

Required actions: Regenerate .pb.c/.pb.h files with new nanopb version if oneofs are used.

Nanopb-0.3.5 (2016-02-13)

Add support for platforms without uint8_t

Rationale: Some platforms cannot access 8-bit sized values directly, and do not define uint8_t. Nanopb previously didn't support these platforms.

Changes: References to uint8_t were replaced with several alternatives, one of them being a new pb_byte_t typedef. This in turn uses uint_least8_t which means the smallest available type.

Required actions: If your platform does not have a standards-compliant stdint.h, it may lack the definition for [u]int_least8_t. This must be added manually, example can be found in extra/pb_syshdr.h.

Error indications: Compiler error: "unknown type name 'uint_least8_t'".

Nanopb-0.3.2 (2015-01-24)

Add support for OneOfs

Rationale: Previously nanopb did not support the oneof construct in .proto files. Those fields were generated as regular optional fields.

Changes: OneOfs are now generated as C unions. Callback fields are not supported inside oneof and generator gives an error.

Required actions: The generator option no_unions can be used to restore old behaviour and to allow callbacks to be used. To use unions, one change is needed: use which_xxxx field to detect which field is present, instead of has_xxxx. Compare the value against MyStruct_myfield_tag.

Error indications: Generator error: "Callback fields inside of oneof are not supported". Compiler error: "Message" has no member named "has_xxxx".

Nanopb-0.3.0 (2014-08-26)

Separate field iterator logic to pb_common.c

Rationale: Originally, the field iteration logic was simple enough to be duplicated in pb_decode.c and pb_encode.c. New field types have made the logic more complex, which required the creation of a new file to contain the common functionality.

Changes: There is a new file, pb_common.c, which must be included in builds.

Required actions: Add pb_common.c to build rules. This file is always required. Either pb_decode.c or pb_encode.c can still be left out if some functionality is not needed.

Error indications: Linker error: undefined reference to pb_field_iter_begin, pb_field_iter_next or similar.

Change data type of field counts to pb_size_t

Rationale: Often nanopb is used with small arrays, such as 255 items or less. Using a full size_t field to store the array count wastes memory if there are many arrays. There already exists parameters PB_FIELD_16BIT and PB_FIELD_32BIT which tell nanopb what is the maximum size of arrays in use.

Changes: Generator will now use pb_size_t for the array _count fields. The size of the type will be controlled by the PB_FIELD_16BIT and PB_FIELD_32BIT compilation time options.

Required actions: Regenerate all .pb.h files. In some cases casts to the pb_size_t type may need to be added in the user code when accessing the _count fields.

Error indications: Incorrect data at runtime, crashes. But note that other changes in the same version already require regenerating the files and have better indications of errors, so this is only an issue for development versions.

Renamed some macros and identifiers

Rationale: Some names in nanopb core were badly chosen and conflicted with ISO C99 reserved names or lacked a prefix. While they haven't caused trouble so far, it is reasonable to switch to non-conflicting names as these are rarely used from user code.

Changes: The following identifier names have changed:

  • Macros:
    • STATIC_ASSERT(x) -> PB_STATIC_ASSERT(x)
    • UNUSED(x) -> PB_UNUSED(x)
  • Include guards:
    • PB_filename -> PB_filename_INCLUDED
  • Structure forward declaration tags:
    • _pb_field_t -> pb_field_s
    • _pb_bytes_array_t -> pb_bytes_array_s
    • _pb_callback_t -> pb_callback_s
    • _pb_extension_type_t -> pb_extension_type_s
    • _pb_extension_t -> pb_extension_s
    • _pb_istream_t -> pb_istream_s
    • _pb_ostream_t -> pb_ostream_s

Required actions: Regenerate all .pb.c files. If you use any of the above identifiers in your application code, perform search-replace to the new name.

Error indications: Compiler errors on lines with the macro/type names.

Nanopb-0.2.9 (2014-08-09)

Change semantics of generator -e option

Rationale: Some compilers do not accept filenames with two dots (like in default extension .pb.c). The -e option to the generator allowed changing the extension, but not skipping the extra dot.

Changes: The -e option in generator will no longer add the prepending dot. The default value has been adjusted accordingly to .pb.c to keep the default behaviour the same as before.

Required actions: Only if using the generator -e option. Add dot before the parameter value on the command line.

Error indications: File not found when trying to compile generated files.

Nanopb-0.2.7 (2014-04-07)

Changed pointer-type bytes field datatype

Rationale: In the initial pointer encoding support since nanopb-0.2.5, the bytes type used a separate pb_bytes_ptr_t type to represent bytes fields. This made it easy to encode data from a separate, user-allocated buffer. However, it made the internal logic more complex and was inconsistent with the other types.

Changes: Dynamically allocated bytes fields now have the pb_bytes_array_t type, just like statically allocated ones.

Required actions: Only if using pointer-type fields with the bytes datatype. Change any access to msg->field.size to msg->field->size. Change any allocation to reserve space of amount PB_BYTES_ARRAY_T_ALLOCSIZE(n). If the data pointer was begin assigned from external source, implement the field using a callback function instead.

Error indications: Compiler error: unknown type name pb_bytes_ptr_t.

Nanopb-0.2.4 (2013-11-07)

Remove the NANOPB_INTERNALS compilation option

Rationale: Having the option in the headers required the functions to be non-static, even if the option is not used. This caused errors on some static analysis tools.

Changes: The \#ifdef and associated functions were removed from the header.

Required actions: Only if the NANOPB_INTERNALS option was previously used. Actions are as listed under nanopb-0.1.3 and nanopb-0.1.6.

Error indications: Compiler warning: implicit declaration of function pb_dec_string, pb_enc_string, or similar.

Nanopb-0.2.1 (2013-04-14)

Callback function signature

Rationale: Previously the auxiliary data to field callbacks was passed as void*. This allowed passing of any data, but made it unnecessarily complex to return a pointer from callback.

Changes: The callback function parameter was changed to void**.

Required actions: You can continue using the old callback style by defining PB_OLD_CALLBACK_STYLE. Recommended action is to:

  • Change the callback signatures to contain void** for decoders and void * const * for encoders.
  • Change the callback function body to use **arginstead ofarg`.

Error indications: Compiler warning: assignment from incompatible pointer type, when initializing funcs.encode or funcs.decode.

Nanopb-0.2.0 (2013-03-02)

Reformatted generated .pb.c file using macros

Rationale: Previously the generator made a list of C pb_field_t initializers in the .pb.c file. This led to a need to regenerate all .pb.c files after even small changes to the pb_field_t definition.

Changes: Macros were added to pb.h which allow for cleaner definition of the .pb.c contents. By changing the macro definitions, changes to the field structure are possible without breaking compatibility with old .pb.c files.

Required actions: Regenerate all .pb.c files from the .proto sources.

Error indications: Compiler warning: implicit declaration of function pb_delta_end.

Changed pb_type_t definitions

Rationale: The pb_type_t was previously an enumeration type. This caused warnings on some compilers when using bitwise operations to set flags inside the values.

Changes: The pb_type_t was changed to typedef uint8_t. The values were changed to #define. Some value names were changed for consistency.

Required actions: Only if you directly access the pb_field_t contents in your own code, something which is not usually done. Needed changes:

  • Change PB_HTYPE_ARRAY to PB_HTYPE_REPEATED.
  • Change PB_HTYPE_CALLBACK to PB_ATYPE() and PB_ATYPE_CALLBACK.

Error indications: Compiler error: PB_HTYPE_ARRAY or PB_HTYPE_CALLBACK undeclared.

Nanopb-0.1.6 (2012-09-02)

Refactored field decoder interface

Rationale: Similarly to field encoders in nanopb-0.1.3.

Changes: New functions with names pb_decode_* were added.

Required actions: By defining NANOPB_INTERNALS, you can still keep using the old functions. Recommended action is to replace any calls with the newer pb_decode_* equivalents.

Error indications: Compiler warning: implicit declaration of function pb_dec_string, pb_dec_varint, pb_dec_submessage or similar.

Nanopb-0.1.3 (2012-06-12)

Refactored field encoder interface

Rationale: The old pb_enc_* functions were designed mostly for the internal use by the core. Because they are internally accessed through function pointers, their signatures had to be common. This led to a confusing interface for external users.

Changes: New functions with names pb_encode_* were added. These have easier to use interfaces. The old functions are now only thin wrappers for the new interface.

Required actions: By defining NANOPB_INTERNALS, you can still keep using the old functions. Recommended action is to replace any calls with the newer pb_encode_* equivalents.

Error indications: Compiler warning: implicit declaration of function pb_enc_string, *pb_enc_varint,pb_enc_submessage\ or similar.