protobuf原理解析-利用protoc-c为xxx.proto生成管理类

1.概述
protobuf是一种google开源的序列化,反序列化工具.
该工具由protoc-c应用程序和protobuf-c动态库两部分组成.

使用步骤为:
(1). 提供自定义的xxx.proto文件,来定义你要序列化和反序列化的类型.
(2). 通过proto-c应用程序,为xxx.proto生成相应的xxx.pb-c.hxxx.pb-c.c这样的代码文件.
生成的代码文件包含了xxx.proto类型的定义,并提供了类型序列化,反向序列化的功能实现.
(3). 现在应用程序需要对xxx.proto中类型执行序列化或反序列化处理时,只需编译时,一起编译xxx.pb-c.c源文件,且编译链接和运行链接时,链接到protobuf-c动态库.这样在应用程序代码中就可引用xxx.pb-c.h中的类型,并调用类型的序列化,反向序列化方法实现类型实例的序列化处理,反向序列化处理.

上述这套序列化,反向序列化方案相比自己重新实现一套的优势在于:
(1). 此开源实现中为兼容性,可扩展性,序列化,反向序列化的效率等都做了大量的考量,且经过了大量的实践验证.本身是非常优秀的实现方案.
(2). 由于这套方案中,类型代码是自动生成的,类型序列化和反向序列化的功能是代码生成时已经支持的.我们只需参考proto文件的规范要求,定义好此文件即可.所以,是比较易于使用的.

2.proto文件
通过概述,我们知道,我们只需定义好proto文件,代码生成,序列化,反向序列化这些均借助protoc-cprotobuf-c即可自动完成.

完备的proto文件规范需要参考此项目的https://developers.google.com/protocol-buffers/docs/proto官方文档.
这里,我们以一个实例,对最关键和常用的部分进行说明.

syntax = "proto2";
package foo;

enum TestEnum {
    VALUENEG123456 = -123456;
    VALUENEG1 = -1;
    VALUE0 = 0;
    VALUE2097152 = 2097152;
    VALUE268435456 = 268435456;
}

message TestInt{
    optional int32 test_int = 1;
    optional int32 test_int2 = 2 [default = 100];
}

message TestClass {
    optional int32 test_int32 = 1;
    optional sint32 test_sint32 = 2;
    optional sfixed32 test_sfixed32 = 3;
    optional int64 test_int64 = 4;
    optional sint64 test_sint64 = 5;
    optional sfixed64 test_sfixed64 = 6;
    optional uint32 test_uint32 = 7;
    optional fixed32 test_fixed32 = 8;
    optional uint64 test_uint64 = 9;
    optional fixed64 test_fixed64 = 10;
    optional float test_float = 11;
    optional double test_double = 12;
    optional bool test_boolean = 13;
    optional string test_string = 14;
    optional bytes test_bytes = 15;
    optional TestEnum test_enum = 16;
    optional TestInt test_class = 17;

    required int32 test_int32_req = 101;
    required sint32 test_sint32_req = 102;
    required sfixed32 test_sfixed32_req = 103;
    required int64 test_int64_req = 104;
    required sint64 test_sint64_req = 105;
    required sfixed64 test_sfixed64_req = 106;
    required uint32 test_uint32_req = 107;
    required fixed32 test_fixed32_req = 108;
    required uint64 test_uint64_req = 109;
    required fixed64 test_fixed64_req = 110;
    required float test_float_req = 111;
    required double test_double_req = 112;
    required bool test_boolean_req = 113;
    required string test_string_req = 114;
    required bytes test_bytes_req = 115;
    required TestEnum test_enum_req = 116;
    required TestInt test_class_req = 117;

    repeated int32 test_int32_rep = 201;
    repeated sint32 test_sint32_rep = 202;
    repeated sfixed32 test_sfixed32_rep = 203;
    repeated int64 test_int64_rep = 204;
    repeated sint64 test_sint64_rep = 205;
    repeated sfixed64 test_sfixed64_rep = 206;
    repeated uint32 test_uint32_rep = 207;
    repeated fixed32 test_fixed32_rep = 208;
    repeated uint64 test_uint64_rep = 209;
    repeated fixed64 test_fixed64_rep = 210;
    repeated float test_float_rep = 211;
    repeated double test_double_rep = 212;
    repeated bool test_boolean_rep = 213;
    repeated string test_string_rep = 214;
    repeated bytes test_bytes_rep = 215;
    repeated TestEnum test_enum_rep = 216;
    repeated TestInt test_class_rep = 217;

    repeated int32 test_int32_rep_p = 301 [packed=true];
    repeated sint32 test_sint32_rep_p = 302 [packed=true];
    repeated sfixed32 test_sfixed32_rep_p = 303 [packed=true];
    repeated int64 test_int64_rep_p = 304 [packed=true];
    repeated sint64 test_sint64_rep_p = 305 [packed=true];
    repeated sfixed64 test_sfixed64_rep_p = 306 [packed=true];
    repeated uint32 test_uint32_rep_p = 307 [packed=true];
    repeated fixed32 test_fixed32_rep_p = 308 [packed=true];
    repeated uint64 test_uint64_rep_p = 309 [packed=true];
    repeated fixed64 test_fixed64_rep_p = 310 [packed=true];
    repeated float test_float_rep_p = 311 [packed=true];
    repeated double test_double_rep_p = 312 [packed=true];
    repeated bool test_boolean_rep_p = 313 [packed=true];
    repeated TestEnum test_enum_rep_p = 316 [packed=true];
}

上述是一个proto文件.
(1). syntax = "proto2"
表示按proto2的语法对这个文件进行解释.
(2). package foo;
表示定义的类型均位于名字为foo的命名空间.由于我们以c语言下的使用进行解析,c语言下生成的代码文件中对命名空间的处理是对类型名字加上对应的前缀.
(3). 定义枚举类型

enum TestEnum {
    VALUENEG123456 = -123456;
    VALUENEG1 = -1;
    VALUE0 = 0;
    VALUE2097152 = 2097152;
    VALUE268435456 = 268435456;
}

我们可以在proto中定义枚举类型.VALUENEG123456 = -123456;这样的内容左边是枚举常量,右边是枚举常量的数值.
(4). 定义消息类型

message TestInt{
    optional int32 test_int = 1;
    optional int32 test_int2 = 2 [default = 100];
}

我们可以在proto中自定义消息类型.类型代码中自定义类型.
optional int32 test_int = 1;这样的内容是在定义此类型下的某个成员(叫字段也可以).
对于自定义类型的每个成员定义,普遍是以下形式:
修饰部分 成员类型 成员名字 = 序号 选项部分;
a. 修饰部分
对于修饰部分必须是:optional,required,repeated三者之一.
a.1. optional
意思是字段值在类型实例中可以不出现,也可以出现一次.
a.2. required
意思是字段值在类型实例中必须出现一次.
a.3. repeated
意思是字段值在类型实例中可以不出现,也可以出现一次或多次.
b. 成员类型
proto中支持的所有成员类型如下:
b.1. int32
b.2. sint32
b.3. sfixed32
b.4 int64
b.5. sint64
b.6. sfixed64
b.7. uint32
b.8. fixed32
b.9. uint64
b.10. fixed64
b.11. float
b.12. double
b.13. bool
b.14. string
b.15. bytes
b.16. 枚举类型
b.17. 自定义类型
b.18. oneof类型
c. 成员名字
d. 序号
单个类型的字段中不可以出现序号相同的情况.
e. 选项
可以利用选项为字段设置默认值.未设置默认值的字段,依据其类型,也可拥有属于此类型的默认值.
repeated修饰的字段,允许设置packed模式.设置和非设置下,此类型序列化和反序列化方式存在差异.

3.生成的代码文件
对上述proto文件执行protoc-c --c_out=. test_normal.proto生成的.h.cpp文件如下:
(1). 头文件

/* Generated by the protocol buffer compiler.  DO NOT EDIT! */
/* Generated from: test_normal.proto */

#ifndef PROTOBUF_C_test_5fnormal_2eproto__INCLUDED
#define PROTOBUF_C_test_5fnormal_2eproto__INCLUDED

#include <protobuf-c/protobuf-c.h>
PROTOBUF_C__BEGIN_DECLS
#if PROTOBUF_C_VERSION_NUMBER < 1000000
# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers.
#elif 1005000 < PROTOBUF_C_MIN_COMPILER_VERSION
# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c.
#endif

// 采用两个下划线连接的方式实现命名空间处理
// 每个proto中的自定义类型拥有一个代码类型
typedef struct Foo__TestInt Foo__TestInt;
typedef struct Foo__TestClass Foo__TestClass;

/* --- enums --- */
// 每个proto中枚举类型拥有一个代码枚举类型
typedef enum _Foo__TestEnum {
   // 借助proto中每项,定义枚举常量,指定常量值
  FOO__TEST_ENUM__VALUENEG123456 = -123456,
  FOO__TEST_ENUM__VALUENEG1 = -1,
  FOO__TEST_ENUM__VALUE0 = 0,
  FOO__TEST_ENUM__VALUE2097152 = 2097152,
  FOO__TEST_ENUM__VALUE268435456 = 268435456
    PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(FOO__TEST_ENUM)
} Foo__TestEnum;

/* --- messages --- */
// 每个proto中定义的消息类型拥有一个代码类型
struct  Foo__TestInt
{
  // 每个proto中自定义类型均在代码类型中首个字段位置内嵌一个ProtobufCMessage实例.
  // 这个ProtobufCMessage实例用于对类型进行描述.
  ProtobufCMessage base;
  // 针对每个optional修饰的类型字段,额外拥有一个hash_字段名来表示此字段存在性
  protobuf_c_boolean has_test_int;
  int32_t test_int;
  protobuf_c_boolean has_test_int2;
  int32_t test_int2;
};

// 每个代码类型,提供初始化类型实例的方法.以宏的形式.
// optional字段的has默认是0,字段值在通过选项指定默认值下,以指定默认值为准.未指定下,每个类型有自己的默认值.
#define FOO__TEST_INT__INIT \
 { PROTOBUF_C_MESSAGE_INIT (&foo__test_int__descriptor) \
    , 0, 0, 0, 100 }

// 1.这里可以看出proto中内置类型和代码类型的对应关系:
// int32			int32_t
// sint32			int32_t
// sfixed32			int32_t
// int64			int64_t
// sint64			int64_t
// sfixed64			int64_t
// uint32			uint32_t
// fixed32			uint32_t
// uint64			uint64_t
// fixed64			uint64_t
// float			float
// double			double
// bool				protobuf_c_boolean
// bytes      		ProtobufCBinaryData
// string           char*
// 为何针对类型int32_t这样的数值类型,设立多个proto类型.是因为这些proto类型会采用不同的序列化,反向序列化方案.

// 2.对optional修饰的字段
// 2.1.针对string,自定义类型采取直接存储指针的方式.
// 2.2.针对其余类型,采用has+类型实例的方式.has用来表示字段内容是否存在.

// 3.对required修饰的字段
// 3.1.针对string,自定义类型采用存储指针的方式.
// 3.2.针对其他类型,采用类型实例的方式.

// 4.对repeated修饰的字段
// 4.1.针对string,自定义类型采用存储元素数目+元素指针集合的方式.
// 4.2.针对其他类型,采用存储元素数目+类型实例集合的方式.
struct  Foo__TestClass
{
  ProtobufCMessage base;
  protobuf_c_boolean has_test_int32;
  int32_t test_int32;
  protobuf_c_boolean has_test_sint32;
  int32_t test_sint32;
  protobuf_c_boolean has_test_sfixed32;
  int32_t test_sfixed32;
  protobuf_c_boolean has_test_int64;
  int64_t test_int64;
  protobuf_c_boolean has_test_sint64;
  int64_t test_sint64;
  protobuf_c_boolean has_test_sfixed64;
  int64_t test_sfixed64;
  protobuf_c_boolean has_test_uint32;
  uint32_t test_uint32;
  protobuf_c_boolean has_test_fixed32;
  uint32_t test_fixed32;
  protobuf_c_boolean has_test_uint64;
  uint64_t test_uint64;
  protobuf_c_boolean has_test_fixed64;
  uint64_t test_fixed64;
  protobuf_c_boolean has_test_float;
  float test_float;
  protobuf_c_boolean has_test_double;
  double test_double;
  protobuf_c_boolean has_test_boolean;
  protobuf_c_boolean test_boolean;
  char *test_string;
  protobuf_c_boolean has_test_bytes;
  ProtobufCBinaryData test_bytes;
  protobuf_c_boolean has_test_enum;
  Foo__TestEnum test_enum;
  Foo__TestInt *test_class;
  int32_t test_int32_req;
  int32_t test_sint32_req;
  int32_t test_sfixed32_req;
  int64_t test_int64_req;
  int64_t test_sint64_req;
  int64_t test_sfixed64_req;
  uint32_t test_uint32_req;
  uint32_t test_fixed32_req;
  uint64_t test_uint64_req;
  uint64_t test_fixed64_req;
  float test_float_req;
  double test_double_req;
  protobuf_c_boolean test_boolean_req;
  char *test_string_req;
  ProtobufCBinaryData test_bytes_req;
  Foo__TestEnum test_enum_req;
  Foo__TestInt *test_class_req;
  size_t n_test_int32_rep;
  int32_t *test_int32_rep;
  size_t n_test_sint32_rep;
  int32_t *test_sint32_rep;
  size_t n_test_sfixed32_rep;
  int32_t *test_sfixed32_rep;
  size_t n_test_int64_rep;
  int64_t *test_int64_rep;
  size_t n_test_sint64_rep;
  int64_t *test_sint64_rep;
  size_t n_test_sfixed64_rep;
  int64_t *test_sfixed64_rep;
  size_t n_test_uint32_rep;
  uint32_t *test_uint32_rep;
  size_t n_test_fixed32_rep;
  uint32_t *test_fixed32_rep;
  size_t n_test_uint64_rep;
  uint64_t *test_uint64_rep;
  size_t n_test_fixed64_rep;
  uint64_t *test_fixed64_rep;
  size_t n_test_float_rep;
  float *test_float_rep;
  size_t n_test_double_rep;
  double *test_double_rep;
  size_t n_test_boolean_rep;
  protobuf_c_boolean *test_boolean_rep;
  size_t n_test_string_rep;
  char **test_string_rep;
  size_t n_test_bytes_rep;
  ProtobufCBinaryData *test_bytes_rep;
  size_t n_test_enum_rep;
  Foo__TestEnum *test_enum_rep;
  size_t n_test_class_rep;
  Foo__TestInt **test_class_rep;
  size_t n_test_int32_rep_p;
  int32_t *test_int32_rep_p;
  size_t n_test_sint32_rep_p;
  int32_t *test_sint32_rep_p;
  size_t n_test_sfixed32_rep_p;
  int32_t *test_sfixed32_rep_p;
  size_t n_test_int64_rep_p;
  int64_t *test_int64_rep_p;
  size_t n_test_sint64_rep_p;
  int64_t *test_sint64_rep_p;
  size_t n_test_sfixed64_rep_p;
  int64_t *test_sfixed64_rep_p;
  size_t n_test_uint32_rep_p;
  uint32_t *test_uint32_rep_p;
  size_t n_test_fixed32_rep_p;
  uint32_t *test_fixed32_rep_p;
  size_t n_test_uint64_rep_p;
  uint64_t *test_uint64_rep_p;
  size_t n_test_fixed64_rep_p;
  uint64_t *test_fixed64_rep_p;
  size_t n_test_float_rep_p;
  float *test_float_rep_p;
  size_t n_test_double_rep_p;
  double *test_double_rep_p;
  size_t n_test_boolean_rep_p;
  protobuf_c_boolean *test_boolean_rep_p;
  size_t n_test_enum_rep_p;
  Foo__TestEnum *test_enum_rep_p;
};

#define FOO__TEST_CLASS__INIT \
 { PROTOBUF_C_MESSAGE_INIT (&foo__test_class__descriptor) \
    , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 0, {0,NULL}, 0, FOO__TEST_ENUM__VALUENEG123456, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, {0,NULL}, FOO__TEST_ENUM__VALUENEG123456, NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL, 0,NULL }

/* Foo__TestInt methods */
// 针对proto中的每个自定义类型,除了提供代码类型.还有方法集合.
// 1.类型实例初始化
void   foo__test_int__init(Foo__TestInt *message);
// 2.获取类型实例序列化尺寸
size_t foo__test_int__get_packed_size(const Foo__TestInt *message);
// 3.将类型实例序列化到指定的缓存区中
size_t foo__test_int__pack(const Foo__TestInt *message, uint8_t *out);
// 4.将类型实例序列化到指定的ProtobufCBuffer类型的缓存区中
size_t foo__test_int__pack_to_buffer(const Foo__TestInt *message, ProtobufCBuffer *buffer);
// 5.提供一个指向类型实例序列化内容的缓存区,通过反向序列化构建并返回类型实例指针
Foo__TestInt * foo__test_int__unpack(ProtobufCAllocator *allocator, size_t len, const uint8_t *data);
// 6.释放类型实例指向对象
void foo__test_int__free_unpacked(Foo__TestInt *message, ProtobufCAllocator *allocator);
/* Foo__TestClass methods */
void foo__test_class__init(Foo__TestClass *message);
size_t foo__test_class__get_packed_size(const Foo__TestClass *message);
size_t foo__test_class__pack(const Foo__TestClass *message, uint8_t *out);
size_t foo__test_class__pack_to_buffer(const Foo__TestClass *message, ProtobufCBuffer *buffer);
Foo__TestClass *foo__test_class__unpack(ProtobufCAllocator *allocator, size_t len, const uint8_t *data);
void foo__test_class__free_unpacked(Foo__TestClass *message, ProtobufCAllocator *allocator);
/* --- per-message closures --- */
// 为每个proto中的自定义类型定义一个方法指针
typedef void (*Foo__TestInt_Closure)(const Foo__TestInt *message, void *closure_data);
typedef void (*Foo__TestClass_Closure)(const Foo__TestClass *message, void *closure_data);
/* --- services --- */
/* --- descriptors --- */
// 这里引用了protobuf-c中的类型定义
// 对于proto中每个定义的枚举类型,存在一个ProtobufCEnumDescriptor.
// 可将其视为关联枚举类型类型定义的等价表达.也可认为是类型定义的元数据.
extern const ProtobufCEnumDescriptor foo__test_enum__descriptor;
// 对于proto中每个定义的自定义类型,存在一个ProtobufCMessageDescriptor.
// 可将其视为关联自定义类型定义的等价表达.也可认为是类型定义的元数据.
extern const ProtobufCMessageDescriptor foo__test_int__descriptor;
extern const ProtobufCMessageDescriptor foo__test_class__descriptor;

/* 实际上protobuf-c中ProtobufCMessage定义如下:
struct ProtobufCMessage {
	const ProtobufCMessageDescriptor *descriptor;
	unsigned n_unknown_fields;
	ProtobufCMessageUnknownField *unknown_fields;
};*/
PROTOBUF_C__END_DECLS
#endif  /* PROTOBUF_C_test_5fnormal_2eproto__INCLUDED */

(2). 源文件

/* Generated by the protocol buffer compiler.  DO NOT EDIT! */
/* Generated from: test_normal.proto */
/* Do not generate deprecated warnings for self */
#ifndef PROTOBUF_C__NO_DEPRECATED
#define PROTOBUF_C__NO_DEPRECATED
#endif
#include "test_normal.pb-c.h"
// proto中自定义类型的方法集
// 1.类型实例初始化
void foo__test_int__init(Foo__TestInt *message)
{
  static const Foo__TestInt init_value = FOO__TEST_INT__INIT;
  *message = init_value;
}

// 2.提供类型实例指针,获取序列化此实例对象所需尺寸
size_t foo__test_int__get_packed_size(const Foo__TestInt *message)
{
  assert(message->base.descriptor == &foo__test_int__descriptor);
  // 这个是protobuf-c动态库中的函数,用于对类型实例计算序列化尺寸
  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}

// 3.将指针指向的类型实例序列化到指定的缓存区中
size_t foo__test_int__pack(const Foo__TestInt *message, uint8_t *out)
{
  assert(message->base.descriptor == &foo__test_int__descriptor);
  // 这个是protobuf-c动态库中的函数,用于将类型实例序列化指定的缓存区中
  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
// 4.将指针指向的类型实例序列化到ProtobufCBuffer类型的缓存区中
size_t foo__test_int__pack_to_buffer(const Foo__TestInt *message, ProtobufCBuffer *buffer)
{
  assert(message->base.descriptor == &foo__test_int__descriptor);
  // 这个是protobuf-c动态库中的函数,用于将类型实例序列化到ProtobufCBuffer类型的缓存区中
  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
// 5.通过提供的指向一个类型实例序列化后的缓存区,创建一个实例对象,用反向序列化来填充内容,并返回
Foo__TestInt * foo__test_int__unpack(ProtobufCAllocator *allocator, size_t len, const uint8_t *data)
{
  // 这个是protobuf-c动态库中的函数,用于通过提供的指向序列化内容的缓存区,创建并利用反向序列化填充并返回一个实例对象
  return (Foo__TestInt *)protobuf_c_message_unpack (&foo__test_int__descriptor, allocator, len, data);
}
// 6.释放提供的实例对象
void   foo__test_int__free_unpacked(Foo__TestInt *message, ProtobufCAllocator *allocator)
{
  if(!message)
    return;
  assert(message->base.descriptor == &foo__test_int__descriptor);
  // 这个是protobuf-c动态库中的函数,用于释放提供的实例对象
  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}

void foo__test_class__init(Foo__TestClass *message)
{
  static const Foo__TestClass init_value = FOO__TEST_CLASS__INIT;
  *message = init_value;
}
size_t foo__test_class__get_packed_size(const Foo__TestClass *message)
{
  assert(message->base.descriptor == &foo__test_class__descriptor);
  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t foo__test_class__pack(const Foo__TestClass *message, uint8_t *out)
{
  assert(message->base.descriptor == &foo__test_class__descriptor);
  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t foo__test_class__pack_to_buffer(const Foo__TestClass *message, ProtobufCBuffer *buffer)
{
  assert(message->base.descriptor == &foo__test_class__descriptor);
  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
Foo__TestClass * foo__test_class__unpack(ProtobufCAllocator *allocator, size_t len, const uint8_t *data)
{
  return (Foo__TestClass *)protobuf_c_message_unpack (&foo__test_class__descriptor, allocator, len, data);
}
void foo__test_class__free_unpacked(Foo__TestClass *message, ProtobufCAllocator *allocator)
{
  if(!message)
    return;
  assert(message->base.descriptor == &foo__test_class__descriptor);
  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}

// 这个对应proto类型定义中提供了默认值的字段的默认值
static const int32_t foo__test_int__test_int2__default_value = 100;
// 针对proto中自定义类型中的每个字段存在一个ProtobufCFieldDescriptor实例
// ProtobufCFieldDescriptor可认为是字段定义的元数据,在代码中以等价的方式包含了proto中的字段定义信息.
static const ProtobufCFieldDescriptor foo__test_int__field_descriptors[2] =
{
  {
  	// 字段名称
    "test_int",
    // 序号
    1,
    // 修饰符
    PROTOBUF_C_LABEL_OPTIONAL,
    // 字段的类型
    PROTOBUF_C_TYPE_INT32,
    // 字段在所在类型中关联部分的偏移
    // 对optional修饰,且存在关联has部分的字段,指向其关联的has部分在代码类型中的偏移
    // 对repeated修饰的字段,指向其关联的元素数目部分在代码类型中的偏移
    // 其他情况下,无意义
    offsetof(Foo__TestInt, has_test_int),
    // 字段自身在所在的代码类型中的偏移
    // 对optional修饰,且存在关联has部分的字段,指向关联has字段后的那个字段在代码类型中的偏移
    // 对repeated修饰的字段,指向其关联的元素数目后的字段在代码类型中的偏移
    // 其他情况,指向代码类型中字段对应部分的偏移
    offsetof(Foo__TestInt, test_int),
    // 当字段类型为proto中枚举类型时,指向类型对应的ProtobufCEnumDescriptor实例对象
    // 当字段类型为proto中自定义消息时,指向类型对应的ProtobufCMessageDescriptor实例对象
    // 其他情况下,为NULL
    NULL,
    // 当字段定义了默认值时,指向其默认值实例对象
    // 其他下,为NULL
    NULL,
    // 字段标志信息.
    // 指定了packed时,含PROTOBUF_C_FIELD_FLAG_PACKED.
    // 指定了deprecated时,含PROTOBUF_C_FIELD_FLAG_DEPRECATED
    // oneof类型字段,含PROTOBUF_C_FIELD_FLAG_ONEOF
    0,             /* flags */
    // 最后三个预留.未被实际使用.
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_int2",
    2,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_INT32,
    offsetof(Foo__TestInt, has_test_int2),
    offsetof(Foo__TestInt, test_int2),
    NULL,
    &foo__test_int__test_int2__default_value,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
};

// 这个结构体是意思是
// 针对每个proto中自定义类型.存在一个对应的field_indices_by_name数组.
// 类型每个字段拥有一个数组项.
// 数组项内容规则:
// 对自定义类型字段按名词排序,排序后的每个字段依次对应一个数组元素.数组元素值是此字段在类型定义中的索引.
// 索引从0开始,通过索引,结合类型对应的field_descriptors数组.可进一步取得索引对应字段的ProtobufCFieldDescriptor.
static const unsigned foo__test_int__field_indices_by_name[] = {
  0,   /* field[0] = test_int */
  1,   /* field[1] = test_int2 */
};
// 针对类型的field_descriptors数组中的元素,然后提取每个元素的序号构成一个内部数组.
// 将此内部数组中数值连续的元素视为一组.
// 类型的number_ranges数组中为内部数组的每一组准备一项.
// 分别记录此组中首个元素值,此组中首个元素的位置索引.
static const ProtobufCIntRange foo__test_int__number_ranges[1 + 1] =
{
  { 1, 0 },
   // 特殊的终止标志
   // {0,索引数组中元素数量(也等于类型中字段数量)}
  { 0, 2 }
};

// 每个proto中自定义类型拥有一个ProtobufCMessageDescriptor实例.来描述类型定义信息.
const ProtobufCMessageDescriptor foo__test_int__descriptor =
{
  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,// 魔数
  "foo.TestInt",// 包含作用域的完整名称
  "TestInt",// 不含作用域的名称
  "Foo__TestInt",// c中类型名称
  "foo",// 作用域名称
  sizeof(Foo__TestInt),// 类型尺寸
  2,// 字段数量
  foo__test_int__field_descriptors,// 关联的字段数组
  foo__test_int__field_indices_by_name,// 关联的field_indices_by_name数组
  1,  // 关联的number_ranges数组中有效项数目
  foo__test_int__number_ranges,// 关联的number_ranges数组
  (ProtobufCMessageInit) foo__test_int__init,// 类型的初始化函数
  // 预留部分
  NULL,NULL,NULL    /* reserved[123] */
};

static const ProtobufCFieldDescriptor foo__test_class__field_descriptors[65] =
{
  {
    "test_int32",
    1,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_INT32,
    offsetof(Foo__TestClass, has_test_int32),
    offsetof(Foo__TestClass, test_int32),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sint32",
    2,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_SINT32,
    offsetof(Foo__TestClass, has_test_sint32),
    offsetof(Foo__TestClass, test_sint32),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sfixed32",
    3,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_SFIXED32,
    offsetof(Foo__TestClass, has_test_sfixed32),
    offsetof(Foo__TestClass, test_sfixed32),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_int64",
    4,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_INT64,
    offsetof(Foo__TestClass, has_test_int64),
    offsetof(Foo__TestClass, test_int64),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sint64",
    5,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_SINT64,
    offsetof(Foo__TestClass, has_test_sint64),
    offsetof(Foo__TestClass, test_sint64),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sfixed64",
    6,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_SFIXED64,
    offsetof(Foo__TestClass, has_test_sfixed64),
    offsetof(Foo__TestClass, test_sfixed64),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_uint32",
    7,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_UINT32,
    offsetof(Foo__TestClass, has_test_uint32),
    offsetof(Foo__TestClass, test_uint32),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_fixed32",
    8,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_FIXED32,
    offsetof(Foo__TestClass, has_test_fixed32),
    offsetof(Foo__TestClass, test_fixed32),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_uint64",
    9,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_UINT64,
    offsetof(Foo__TestClass, has_test_uint64),
    offsetof(Foo__TestClass, test_uint64),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_fixed64",
    10,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_FIXED64,
    offsetof(Foo__TestClass, has_test_fixed64),
    offsetof(Foo__TestClass, test_fixed64),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_float",
    11,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_FLOAT,
    offsetof(Foo__TestClass, has_test_float),
    offsetof(Foo__TestClass, test_float),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_double",
    12,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_DOUBLE,
    offsetof(Foo__TestClass, has_test_double),
    offsetof(Foo__TestClass, test_double),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_boolean",
    13,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_BOOL,
    offsetof(Foo__TestClass, has_test_boolean),
    offsetof(Foo__TestClass, test_boolean),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_string",
    14,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_STRING,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_string),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_bytes",
    15,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_BYTES,
    offsetof(Foo__TestClass, has_test_bytes),
    offsetof(Foo__TestClass, test_bytes),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_enum",
    16,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_ENUM,
    offsetof(Foo__TestClass, has_test_enum),
    offsetof(Foo__TestClass, test_enum),
    &foo__test_enum__descriptor,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_class",
    17,
    PROTOBUF_C_LABEL_OPTIONAL,
    PROTOBUF_C_TYPE_MESSAGE,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_class),
    &foo__test_int__descriptor,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_int32_req",
    101,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_INT32,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_int32_req),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sint32_req",
    102,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_SINT32,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_sint32_req),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sfixed32_req",
    103,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_SFIXED32,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_sfixed32_req),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_int64_req",
    104,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_INT64,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_int64_req),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sint64_req",
    105,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_SINT64,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_sint64_req),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sfixed64_req",
    106,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_SFIXED64,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_sfixed64_req),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_uint32_req",
    107,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_UINT32,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_uint32_req),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_fixed32_req",
    108,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_FIXED32,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_fixed32_req),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_uint64_req",
    109,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_UINT64,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_uint64_req),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_fixed64_req",
    110,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_FIXED64,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_fixed64_req),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_float_req",
    111,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_FLOAT,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_float_req),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_double_req",
    112,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_DOUBLE,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_double_req),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_boolean_req",
    113,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_BOOL,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_boolean_req),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_string_req",
    114,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_STRING,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_string_req),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_bytes_req",
    115,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_BYTES,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_bytes_req),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_enum_req",
    116,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_ENUM,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_enum_req),
    &foo__test_enum__descriptor,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_class_req",
    117,
    PROTOBUF_C_LABEL_REQUIRED,
    PROTOBUF_C_TYPE_MESSAGE,
    0,   /* quantifier_offset */
    offsetof(Foo__TestClass, test_class_req),
    &foo__test_int__descriptor,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_int32_rep",
    201,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_INT32,
    offsetof(Foo__TestClass, n_test_int32_rep),
    offsetof(Foo__TestClass, test_int32_rep),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sint32_rep",
    202,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_SINT32,
    offsetof(Foo__TestClass, n_test_sint32_rep),
    offsetof(Foo__TestClass, test_sint32_rep),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sfixed32_rep",
    203,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_SFIXED32,
    offsetof(Foo__TestClass, n_test_sfixed32_rep),
    offsetof(Foo__TestClass, test_sfixed32_rep),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_int64_rep",
    204,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_INT64,
    offsetof(Foo__TestClass, n_test_int64_rep),
    offsetof(Foo__TestClass, test_int64_rep),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sint64_rep",
    205,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_SINT64,
    offsetof(Foo__TestClass, n_test_sint64_rep),
    offsetof(Foo__TestClass, test_sint64_rep),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sfixed64_rep",
    206,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_SFIXED64,
    offsetof(Foo__TestClass, n_test_sfixed64_rep),
    offsetof(Foo__TestClass, test_sfixed64_rep),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_uint32_rep",
    207,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_UINT32,
    offsetof(Foo__TestClass, n_test_uint32_rep),
    offsetof(Foo__TestClass, test_uint32_rep),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_fixed32_rep",
    208,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_FIXED32,
    offsetof(Foo__TestClass, n_test_fixed32_rep),
    offsetof(Foo__TestClass, test_fixed32_rep),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_uint64_rep",
    209,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_UINT64,
    offsetof(Foo__TestClass, n_test_uint64_rep),
    offsetof(Foo__TestClass, test_uint64_rep),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_fixed64_rep",
    210,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_FIXED64,
    offsetof(Foo__TestClass, n_test_fixed64_rep),
    offsetof(Foo__TestClass, test_fixed64_rep),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_float_rep",
    211,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_FLOAT,
    offsetof(Foo__TestClass, n_test_float_rep),
    offsetof(Foo__TestClass, test_float_rep),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_double_rep",
    212,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_DOUBLE,
    offsetof(Foo__TestClass, n_test_double_rep),
    offsetof(Foo__TestClass, test_double_rep),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_boolean_rep",
    213,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_BOOL,
    offsetof(Foo__TestClass, n_test_boolean_rep),
    offsetof(Foo__TestClass, test_boolean_rep),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_string_rep",
    214,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_STRING,
    offsetof(Foo__TestClass, n_test_string_rep),
    offsetof(Foo__TestClass, test_string_rep),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_bytes_rep",
    215,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_BYTES,
    offsetof(Foo__TestClass, n_test_bytes_rep),
    offsetof(Foo__TestClass, test_bytes_rep),
    NULL,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_enum_rep",
    216,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_ENUM,
    offsetof(Foo__TestClass, n_test_enum_rep),
    offsetof(Foo__TestClass, test_enum_rep),
    &foo__test_enum__descriptor,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_class_rep",
    217,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_MESSAGE,
    offsetof(Foo__TestClass, n_test_class_rep),
    offsetof(Foo__TestClass, test_class_rep),
    &foo__test_int__descriptor,
    NULL,
    0,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_int32_rep_p",
    301,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_INT32,
    offsetof(Foo__TestClass, n_test_int32_rep_p),
    offsetof(Foo__TestClass, test_int32_rep_p),
    NULL,
    NULL,
    PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sint32_rep_p",
    302,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_SINT32,
    offsetof(Foo__TestClass, n_test_sint32_rep_p),
    offsetof(Foo__TestClass, test_sint32_rep_p),
    NULL,
    NULL,
    PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sfixed32_rep_p",
    303,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_SFIXED32,
    offsetof(Foo__TestClass, n_test_sfixed32_rep_p),
    offsetof(Foo__TestClass, test_sfixed32_rep_p),
    NULL,
    NULL,
    PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_int64_rep_p",
    304,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_INT64,
    offsetof(Foo__TestClass, n_test_int64_rep_p),
    offsetof(Foo__TestClass, test_int64_rep_p),
    NULL,
    NULL,
    PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sint64_rep_p",
    305,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_SINT64,
    offsetof(Foo__TestClass, n_test_sint64_rep_p),
    offsetof(Foo__TestClass, test_sint64_rep_p),
    NULL,
    NULL,
    PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_sfixed64_rep_p",
    306,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_SFIXED64,
    offsetof(Foo__TestClass, n_test_sfixed64_rep_p),
    offsetof(Foo__TestClass, test_sfixed64_rep_p),
    NULL,
    NULL,
    PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_uint32_rep_p",
    307,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_UINT32,
    offsetof(Foo__TestClass, n_test_uint32_rep_p),
    offsetof(Foo__TestClass, test_uint32_rep_p),
    NULL,
    NULL,
    PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_fixed32_rep_p",
    308,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_FIXED32,
    offsetof(Foo__TestClass, n_test_fixed32_rep_p),
    offsetof(Foo__TestClass, test_fixed32_rep_p),
    NULL,
    NULL,
    PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_uint64_rep_p",
    309,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_UINT64,
    offsetof(Foo__TestClass, n_test_uint64_rep_p),
    offsetof(Foo__TestClass, test_uint64_rep_p),
    NULL,
    NULL,
    PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_fixed64_rep_p",
    310,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_FIXED64,
    offsetof(Foo__TestClass, n_test_fixed64_rep_p),
    offsetof(Foo__TestClass, test_fixed64_rep_p),
    NULL,
    NULL,
    PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_float_rep_p",
    311,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_FLOAT,
    offsetof(Foo__TestClass, n_test_float_rep_p),
    offsetof(Foo__TestClass, test_float_rep_p),
    NULL,
    NULL,
    PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_double_rep_p",
    312,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_DOUBLE,
    offsetof(Foo__TestClass, n_test_double_rep_p),
    offsetof(Foo__TestClass, test_double_rep_p),
    NULL,
    NULL,
    PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_boolean_rep_p",
    313,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_BOOL,
    offsetof(Foo__TestClass, n_test_boolean_rep_p),
    offsetof(Foo__TestClass, test_boolean_rep_p),
    NULL,
    NULL,
    PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
  {
    "test_enum_rep_p",
    316,
    PROTOBUF_C_LABEL_REPEATED,
    PROTOBUF_C_TYPE_ENUM,
    offsetof(Foo__TestClass, n_test_enum_rep_p),
    offsetof(Foo__TestClass, test_enum_rep_p),
    &foo__test_enum__descriptor,
    NULL,
    PROTOBUF_C_FIELD_FLAG_PACKED,             /* flags */
    0,NULL,NULL    /* reserved1,reserved2, etc */
  },
};
static const unsigned foo__test_class__field_indices_by_name[] = {
  12,   /* field[12] = test_boolean */
  46,   /* field[46] = test_boolean_rep */
  63,   /* field[63] = test_boolean_rep_p */
  29,   /* field[29] = test_boolean_req */
  14,   /* field[14] = test_bytes */
  48,   /* field[48] = test_bytes_rep */
  31,   /* field[31] = test_bytes_req */
  16,   /* field[16] = test_class */
  50,   /* field[50] = test_class_rep */
  33,   /* field[33] = test_class_req */
  11,   /* field[11] = test_double */
  45,   /* field[45] = test_double_rep */
  62,   /* field[62] = test_double_rep_p */
  28,   /* field[28] = test_double_req */
  15,   /* field[15] = test_enum */
  49,   /* field[49] = test_enum_rep */
  64,   /* field[64] = test_enum_rep_p */
  32,   /* field[32] = test_enum_req */
  7,   /* field[7] = test_fixed32 */
  41,   /* field[41] = test_fixed32_rep */
  58,   /* field[58] = test_fixed32_rep_p */
  24,   /* field[24] = test_fixed32_req */
  9,   /* field[9] = test_fixed64 */
  43,   /* field[43] = test_fixed64_rep */
  60,   /* field[60] = test_fixed64_rep_p */
  26,   /* field[26] = test_fixed64_req */
  10,   /* field[10] = test_float */
  44,   /* field[44] = test_float_rep */
  61,   /* field[61] = test_float_rep_p */
  27,   /* field[27] = test_float_req */
  0,   /* field[0] = test_int32 */
  34,   /* field[34] = test_int32_rep */
  51,   /* field[51] = test_int32_rep_p */
  17,   /* field[17] = test_int32_req */
  3,   /* field[3] = test_int64 */
  37,   /* field[37] = test_int64_rep */
  54,   /* field[54] = test_int64_rep_p */
  20,   /* field[20] = test_int64_req */
  2,   /* field[2] = test_sfixed32 */
  36,   /* field[36] = test_sfixed32_rep */
  53,   /* field[53] = test_sfixed32_rep_p */
  19,   /* field[19] = test_sfixed32_req */
  5,   /* field[5] = test_sfixed64 */
  39,   /* field[39] = test_sfixed64_rep */
  56,   /* field[56] = test_sfixed64_rep_p */
  22,   /* field[22] = test_sfixed64_req */
  1,   /* field[1] = test_sint32 */
  35,   /* field[35] = test_sint32_rep */
  52,   /* field[52] = test_sint32_rep_p */
  18,   /* field[18] = test_sint32_req */
  4,   /* field[4] = test_sint64 */
  38,   /* field[38] = test_sint64_rep */
  55,   /* field[55] = test_sint64_rep_p */
  21,   /* field[21] = test_sint64_req */
  13,   /* field[13] = test_string */
  47,   /* field[47] = test_string_rep */
  30,   /* field[30] = test_string_req */
  6,   /* field[6] = test_uint32 */
  40,   /* field[40] = test_uint32_rep */
  57,   /* field[57] = test_uint32_rep_p */
  23,   /* field[23] = test_uint32_req */
  8,   /* field[8] = test_uint64 */
  42,   /* field[42] = test_uint64_rep */
  59,   /* field[59] = test_uint64_rep_p */
  25,   /* field[25] = test_uint64_req */
};
static const ProtobufCIntRange foo__test_class__number_ranges[5 + 1] =
{
  { 1, 0 },
  { 101, 17 },
  { 201, 34 },
  { 301, 51 },
  { 316, 64 },
  { 0, 65 }
};
const ProtobufCMessageDescriptor foo__test_class__descriptor =
{
  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
  "foo.TestClass",
  "TestClass",
  "Foo__TestClass",
  "foo",
  sizeof(Foo__TestClass),
  65,
  foo__test_class__field_descriptors,
  foo__test_class__field_indices_by_name,
  5,  foo__test_class__number_ranges,
  (ProtobufCMessageInit) foo__test_class__init,
  NULL,NULL,NULL    /* reserved[123] */
};
// 针对proto中的自定义枚举类型
// 存在一个对应的enum_values_by_number数组.
// 数组每一项,三个元素分别是枚举常量名称,包含作用域类名的枚举常量完整名称,枚举常量数值
// 这个数组类似自定义类型的字段数组
static const ProtobufCEnumValue foo__test_enum__enum_values_by_number[5] =
{
  { "VALUENEG123456", "FOO__TEST_ENUM__VALUENEG123456", -123456 },
  { "VALUENEG1", "FOO__TEST_ENUM__VALUENEG1", -1 },
  { "VALUE0", "FOO__TEST_ENUM__VALUE0", 0 },
  { "VALUE2097152", "FOO__TEST_ENUM__VALUE2097152", 2097152 },
  { "VALUE268435456", "FOO__TEST_ENUM__VALUE268435456", 268435456 },
};
// 针对枚举类型也存在value_ranges数组.
static const ProtobufCIntRange foo__test_enum__value_ranges[] = {
{-123456, 0},{-1, 1},{2097152, 3},{268435456, 4},{0, 5}
};
// 针对枚举类型的values_by_name数组.
// 每个枚举常量对应一项,项按枚举常量名称排序.
// 每一项的含两个元素,一个元素是枚举常量名称,一个元素是枚举常量在enum_values_by_number数组中的索引.
static const ProtobufCEnumValueIndex foo__test_enum__enum_values_by_name[5] =
{
  { "VALUE0", 2 },
  { "VALUE2097152", 3 },
  { "VALUE268435456", 4 },
  { "VALUENEG1", 1 },
  { "VALUENEG123456", 0 },
};
// 针对每个枚举类型存在一个descriptor用于描述类型定义
const ProtobufCEnumDescriptor foo__test_enum__descriptor =
{
  PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,// 魔数
  "foo.TestEnum",// 含作用域的完整名称
  "TestEnum",// 类型名称
  "Foo__TestEnum",// c语言中的类型名称
  "foo",// 作用域名称
  5,// 字段数量.即枚举常量个数.
  foo__test_enum__enum_values_by_number,// enum_values_by_number数组
  5,// 字段数量
  foo__test_enum__enum_values_by_name,// enum_values_by_name数组
  4,// value_ranges数组有效项数量
  foo__test_enum__value_ranges,
  // 预留字段
  NULL,NULL,NULL,NULL   /* reserved[1234] */
};
  • 28
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 当在终端或命令行中使用似于wget或curl等下载工具时,出现downloading v3.1.0/protobuf-cpp-3.1.0.tar.gz...的提示意味着正在下载protobuf-cpp-3.1.0.tar.gz这个文件。这通常是下载一个开源软件包或源代码。 protobuf-cpp是Google开发的一种高效的序列化数据结构的工具,能够将数据以二进制形式进行编码并进行传输和存储。protobuf-cpp软件包包含了编译器和相应的库文件,以及开发人员使用protobuf-cpp的各种实用程序和示例代码。在下载这个软件包之前,需要检查自己是否已经安装了编译器和相关的库文件,以便可以正确地编译和使用该软件包。 下载完成后,用户可以将protobuf-cpp集成到他们的项目中,利用这个功能强大的工具来序列化和反序列化数据。如果用户遇到了任何问题或需要进一步的帮助,可以去官方网站或社区寻求支持和反馈。 ### 回答2: 出现downloading v3.1.0/protobuf-cpp-3.1.0.tar.gz是指正在下载谷歌开发的 Protocol Buffers 3.1.0 版本中的C++实现库protobuf的软件压缩文件,这是一种轻量级高效数据交换格式,可用于各种服务间的数据通信,同时也是很多开源软件的重要依赖库之一。当出现downloading v3.1.0/protobuf-cpp-3.1.0.tar.gz...时,一般是因为用户正在使用支持自动化编译和依赖管理的软件管理器,如yum、apt-get或者brew等,这些工具会自动下载并安装所需要的软件库及其依赖,极大地方便了程序开发者和系统管理员的工作。同时,这个过程也需要一定的网络连接和下载时间,用户必须确保网络畅通并耐心等待,以保证软件的正常安装和使用。 ### 回答3: 这是提示正在下载版本为3.1.0的protobuf-cpp.tar.gz文件,protobuf-cpp是一种轻量级的数据交换格式,常用于不同系统间的数据通信。在下载过程中可能会出现下载速度变慢或者下载失败等情况,需要注意网络状况和服务器状态。如果下载失败,可以尝试重新下载或者通过其他途径获取所需文件。同时也需要注意要下载正确版本的文件,以避免后续的代码运行问题。下载完成后,需要将文件正确地放置到相应的目录下,并进行相关配置和编译工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

raindayinrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值