aosp12/external/grpc-grpc/third_party/nanopb/docs/index.rst

128 lines
5.3 KiB
ReStructuredText
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

=============================================
Nanopb: Protocol Buffers with small code size
=============================================
.. include :: menu.rst
Nanopb is an ANSI-C library for encoding and decoding messages in Google's `Protocol Buffers`__ format with minimal requirements for RAM and code space.
It is primarily suitable for 32-bit microcontrollers.
__ https://developers.google.com/protocol-buffers/docs/reference/overview
Overall structure
=================
For the runtime program, you always need *pb.h* for type declarations.
Depending on whether you want to encode, decode, or both, you also need *pb_encode.h/c* or *pb_decode.h/c*.
The high-level encoding and decoding functions take an array of *pb_field_t* structures, which describes the fields of a message structure. Usually you want these autogenerated from a *.proto* file. The tool script *nanopb_generator.py* accomplishes this.
.. image:: generator_flow.png
So a typical project might include these files:
1) Nanopb runtime library:
- pb.h
- pb_common.h and pb_common.c (always needed)
- pb_decode.h and pb_decode.c (needed for decoding messages)
- pb_encode.h and pb_encode.c (needed for encoding messages)
2) Protocol description (you can have many):
- person.proto (just an example)
- person.pb.c (autogenerated, contains initializers for const arrays)
- person.pb.h (autogenerated, contains type declarations)
Features and limitations
========================
**Features**
#) Pure C runtime
#) Small code size (210 kB depending on processor, plus any message definitions)
#) Small ram usage (typically ~300 bytes, plus any message structs)
#) Allows specifying maximum size for strings and arrays, so that they can be allocated statically.
#) No malloc needed: everything can be allocated statically or on the stack. Optional malloc support available.
#) You can use either encoder or decoder alone to cut the code size in half.
#) Support for most protobuf features, including: all data types, nested submessages, default values, repeated and optional fields, oneofs, packed arrays, extension fields.
#) Callback mechanism for handling messages larger than can fit in available RAM.
#) Extensive set of tests.
**Limitations**
#) Some speed has been sacrificed for code size.
#) Encoding is focused on writing to streams. For memory buffers only it could be made more efficient.
#) The deprecated Protocol Buffers feature called "groups" is not supported.
#) Fields in the generated structs are ordered by the tag number, instead of the natural ordering in .proto file.
#) Unknown fields are not preserved when decoding and re-encoding a message.
#) Reflection (runtime introspection) is not supported. E.g. you can't request a field by giving its name in a string.
#) Numeric arrays are always encoded as packed, even if not marked as packed in .proto.
#) Cyclic references between messages are supported only in callback and malloc mode.
Getting started
===============
For starters, consider this simple message::
message Example {
required int32 value = 1;
}
Save this in *message.proto* and compile it::
user@host:~$ protoc -omessage.pb message.proto
user@host:~$ python nanopb/generator/nanopb_generator.py message.pb
You should now have in *message.pb.h*::
typedef struct {
int32_t value;
} Example;
extern const pb_field_t Example_fields[2];
Now in your main program do this to encode a message::
Example mymessage = {42};
uint8_t buffer[10];
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
pb_encode(&stream, Example_fields, &mymessage);
After that, buffer will contain the encoded message.
The number of bytes in the message is stored in *stream.bytes_written*.
You can feed the message to *protoc --decode=Example message.proto* to verify its validity.
For a complete example of the simple case, see *example/simple.c*.
For a more complex example with network interface, see the *example/network_server* subdirectory.
Compiler requirements
=====================
Nanopb should compile with most ansi-C compatible compilers. It however
requires a few header files to be available:
#) *string.h*, with these functions: *strlen*, *memcpy*, *memset*
#) *stdint.h*, for definitions of *int32_t* etc.
#) *stddef.h*, for definition of *size_t*
#) *stdbool.h*, for definition of *bool*
If these header files do not come with your compiler, you can use the
file *extra/pb_syshdr.h* instead. It contains an example of how to provide
the dependencies. You may have to edit it a bit to suit your custom platform.
To use the pb_syshdr.h, define *PB_SYSTEM_HEADER* as *"pb_syshdr.h"* (including the quotes).
Similarly, you can provide a custom include file, which should provide all the dependencies
listed above.
Running the test cases
======================
Extensive unittests and test cases are included under the *tests* folder.
To build the tests, you will need the `scons`__ build system. The tests should
be runnable on most platforms. Windows and Linux builds are regularly tested.
__ http://www.scons.org/
In addition to the build system, you will also need a working Google Protocol
Buffers *protoc* compiler, and the Python bindings for Protocol Buffers. On
Debian-based systems, install the following packages: *protobuf-compiler*,
*python-protobuf* and *libprotobuf-dev*.