Create a message descriptor type.
This replaces the sentinel at the end of the pb_field_t array for each message type. git-svn-id: https://svn.kapsi.fi/jpa/nanopb-dev@1007 e3a754e5-d11d-0410-8d38-ebb782a927b9
This commit is contained in:
committed by
Petteri Aimonen
parent
dcf43a6416
commit
43b8e20744
@@ -74,7 +74,7 @@ This is the way to get the size of the message without storing it anywhere::
|
||||
|
||||
Person myperson = ...;
|
||||
pb_ostream_t sizestream = {0};
|
||||
pb_encode(&sizestream, Person_fields, &myperson);
|
||||
pb_encode(&sizestream, Person_msg, &myperson);
|
||||
printf("Encoded size is %d\n", sizestream.bytes_written);
|
||||
|
||||
**Example 2:**
|
||||
@@ -221,10 +221,10 @@ This callback reads multiple integers and prints them::
|
||||
return true;
|
||||
}
|
||||
|
||||
Field description array
|
||||
=======================
|
||||
Message descriptor
|
||||
==================
|
||||
|
||||
For using the *pb_encode* and *pb_decode* functions, you need an array of pb_field_t constants describing the structure you wish to encode. This description is usually autogenerated from .proto file.
|
||||
For using the *pb_encode* and *pb_decode* functions, you need a message descriptor describing the structure you wish to encode. This description is usually autogenerated from .proto file.
|
||||
|
||||
For example this submessage in the Person.proto file::
|
||||
|
||||
@@ -235,20 +235,27 @@ For example this submessage in the Person.proto file::
|
||||
}
|
||||
}
|
||||
|
||||
generates this field description array for the structure *Person_PhoneNumber*::
|
||||
generates these declarations and definitions for the structure *Person_PhoneNumber*::
|
||||
|
||||
typedef PB_MSG_STRUCT(2) Person_PhoneNumber_msg_t;
|
||||
extern const Person_PhoneNumber_msg_t Person_PhoneNumber_real_msg;
|
||||
#define Person_PhoneNumber_msg ((const pb_message_t*)&Person_PhoneNumber_real_msg)
|
||||
|
||||
const Person_PhoneNumber_msg_t Person_PhoneNumber_real_msg = {
|
||||
2,
|
||||
{
|
||||
|
||||
const pb_field_t Person_PhoneNumber_fields[3] = {
|
||||
{1, PB_HTYPE_REQUIRED | PB_LTYPE_STRING,
|
||||
offsetof(Person_PhoneNumber, number), 0,
|
||||
pb_membersize(Person_PhoneNumber, number), 0, 0},
|
||||
|
||||
{2, PB_HTYPE_OPTIONAL | PB_LTYPE_VARINT,
|
||||
pb_delta(Person_PhoneNumber, type, number),
|
||||
pb_delta_end(Person_PhoneNumber, type, number),
|
||||
pb_delta(Person_PhoneNumber, has_type, type),
|
||||
pb_membersize(Person_PhoneNumber, type), 0,
|
||||
&Person_PhoneNumber_type_default},
|
||||
|
||||
PB_LAST_FIELD
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ So a typical project might include these files:
|
||||
- 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.c (autogenerated, contains initializers for message descriptors)
|
||||
- person.pb.h (autogenerated, contains type declarations)
|
||||
|
||||
Features and limitations
|
||||
@@ -74,14 +74,16 @@ You should now have in *message.pb.h*::
|
||||
int32_t value;
|
||||
} Example;
|
||||
|
||||
extern const pb_field_t Example_fields[2];
|
||||
typedef PB_MSG_STRUCT(1) Example_msg_t;
|
||||
extern const Example_msg_t Example_real_msg;
|
||||
#define Example_msg ((const pb_message_t*)&Example_real_msg)
|
||||
|
||||
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);
|
||||
pb_encode(&stream, Example_msg, &mymessage);
|
||||
|
||||
After that, buffer will contain the encoded message.
|
||||
The number of bytes in the message is stored in *stream.bytes_written*.
|
||||
|
||||
@@ -140,14 +140,14 @@ pb_encode
|
||||
---------
|
||||
Encodes the contents of a structure as a protocol buffers message and writes it to output stream. ::
|
||||
|
||||
bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
|
||||
bool pb_encode(pb_ostream_t *stream, const pb_message_t *msg, const void *src_struct);
|
||||
|
||||
:stream: Output stream to write to.
|
||||
:fields: A field description array, usually autogenerated.
|
||||
:msg: A message descriptor, usually autogenerated.
|
||||
:src_struct: Pointer to the data that will be serialized.
|
||||
:returns: True on success, false on IO error, on detectable errors in field description, or if a field encoder returns false.
|
||||
|
||||
Normally pb_encode simply walks through the fields description array and serializes each field in turn. However, submessages must be serialized twice: first to calculate their size and then to actually write them to output. This causes some constraints for callback fields, which must return the same data on every call.
|
||||
Normally pb_encode simply walks through the fields description array inside the message descriptor and serializes each field in turn. However, submessages must be serialized twice: first to calculate their size and then to actually write them to output. This causes some constraints for callback fields, which must return the same data on every call.
|
||||
|
||||
pb_encode_varint
|
||||
----------------
|
||||
@@ -289,7 +289,7 @@ Field encoder for PB_LTYPE_SUBMESSAGE. Calls `pb_encode`_ to perform the actual
|
||||
bool pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src);
|
||||
|
||||
:stream: Output stream to write to.
|
||||
:field: Field description structure. The *ptr* field must be a pointer to a field description array for the submessage.
|
||||
:field: Field description structure. The *ptr* field must be a pointer to a valid *pb_message_t* descriptor for the submessage.
|
||||
:src: Pointer to the structure where submessage data is.
|
||||
:returns: True on success, false on IO errors, pb_encode errors or if submessage size changes between calls.
|
||||
|
||||
@@ -355,10 +355,10 @@ pb_decode
|
||||
---------
|
||||
Read and decode all fields of a structure. Reads until EOF on input stream. ::
|
||||
|
||||
bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
bool pb_decode(pb_istream_t *stream, const pb_message_t *msg, void *dest_struct);
|
||||
|
||||
:stream: Input stream to read from.
|
||||
:fields: A field description array. Usually autogenerated.
|
||||
:msg: A message descriptor. Usually autogenerated.
|
||||
:dest_struct: Pointer to structure where data will be stored.
|
||||
:returns: True on success, false on IO error, on detectable errors in field description, if a field encoder returns false or if a required field is missing.
|
||||
|
||||
@@ -459,5 +459,5 @@ Field decoder for PB_LTYPE_SUBMESSAGE. Calls `pb_decode`_ to perform the actual
|
||||
:dest: Pointer to the destination structure.
|
||||
:returns: True on success, false on IO error or if `pb_decode`_ fails.
|
||||
|
||||
The *field->ptr* should be a pointer to *pb_field_t* array describing the submessage.
|
||||
The *field->ptr* should be a pointer to *pb_message_t* describing the submessage.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user