shiyilei / protobuf-c

Automatically exported from code.google.com/p/protobuf-c
BSD 3-Clause "New" or "Revised" License
0 stars 0 forks source link

Enum encoding #69

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. Cross-Compiled protobuf-c.c v.0.15 with armcc for target ARM based 
big-endian device and not setting "IS_LITTLE_ENDIAN". Commented "static inline" 
declarations and changed "alloca" to "malloc".
2. Defined a .proto file with an ENUM inside a message following a field as the 
enum type. (enum has four members with values 0-4) 
3. Compiled .pb-c.h and .pb-c.c successfully.

What is the expected output? What do you see instead?
All int and string types are packed/unpacked correctly except the enum value. 
The enum value converts to little endian and occupies more bytes than it should 
for a single byte value (as uint32) in the packed message. For example value 1 
is translated to 16777216 (=0x01 00 00 00). Same is with other values. Only 
value zero is read successfully however it again occupies four bytes in the 
packed message.

What version of the product are you using? On what operating system?
protoc-c version 0.15 - Host machine is windows VS2005 and the target machine 
is ARM-THUMB cpu.

Please provide any additional information below.
Attached is the test .proto file and corresponding packed binary message.
values set are:
a=4;
b=3;
ee=1;

Original issue reported on code.google.com by Farrokh....@gmail.com on 1 Sep 2011 at 12:02

Attachments:

GoogleCodeExporter commented 8 years ago
I solved the problem, it was a compiler issue but it'll be nice for protoc-c to 
consider such situation in later releases or at least warn the user in docs, 
notes, etc. Here's the cause of the problem:

ANSI C defines no fixed type size for enums but limits the maximum size, e.g. 
int. Many compilers, specially in case device programming optimize enum 
storage. In my case, the arm compiler saves the enum value as a char, short or 
int (maximum) depending on the value. For example a vlue of 9 will be saved as 
a one byte char, while 20,000 will be saved as short. However since the maximum 
value is int (4 bytes in my case), then the struct representing the message in 
.proto file assigns 4 bytes to the enum field. Now say that my enum value is 1 
which takes one byte in my machine. Now suppose that "offsetof(msg_struct, 
my_enum)" return 16. In my big-endian machine the pointer returned for the 
offset points to a 4 bytes block of "0x01 00 00 00" while the correct value 
should have been "0x00 00 00 01". 
I used the -fy switch to force the compiler to store enums as integers.

Original comment by Farrokh....@gmail.com on 27 Sep 2011 at 10:52

GoogleCodeExporter commented 8 years ago
I have been aware of this problem.  I'm surprised not many compilers support 
small enums nowadays.

I am torn between supporting a member of the enum descriptor that is the sizeof 
the enum, or adding into the code a macro like:  
__PROTOBUF_C_ENSURE_ENUM_IS_32BITS(MACRO_NAME).

A standard implementation of this would be:

#define __PROTOBUF_C_ENSURE_ENUM_IS_32BITS(MACRO_NAME) \
  PROTOBUF_C_ENSURE_ENUM_IS_32_BITS__##MACRO_NAME = 0x10000

Original comment by lahike...@gmail.com on 2 Nov 2011 at 4:41

GoogleCodeExporter commented 8 years ago
Fix committed to subversion to ensure enums are the size of ints.

Original comment by lahike...@gmail.com on 12 Nov 2011 at 2:32

GoogleCodeExporter commented 8 years ago

Original comment by lahike...@gmail.com on 12 Nov 2011 at 2:33