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

2024-03-20 18:36

本文主要是介绍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 = 268435456PROTOBUF_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实例对象// 其他情况下,为NULLNULL,// 当字段定义了默认值时,指向其默认值实例对象// 其他下,为NULLNULL,// 字段标志信息.// 指定了packed时,含PROTOBUF_C_FIELD_FLAG_PACKED.// 指定了deprecated时,含PROTOBUF_C_FIELD_FLAG_DEPRECATED// oneof类型字段,含PROTOBUF_C_FIELD_FLAG_ONEOF0,             /* 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] */
};

这篇关于protobuf原理解析-利用protoc-c为xxx.proto生成管理类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/830379

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

AI一键生成 PPT

AI一键生成 PPT 操作步骤 作为一名打工人,是不是经常需要制作各种PPT来分享我的生活和想法。但是,你们知道,有时候灵感来了,时间却不够用了!😩直到我发现了Kimi AI——一个能够自动生成PPT的神奇助手!🌟 什么是Kimi? 一款月之暗面科技有限公司开发的AI办公工具,帮助用户快速生成高质量的演示文稿。 无论你是职场人士、学生还是教师,Kimi都能够为你的办公文

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

hdu4407(容斥原理)

题意:给一串数字1,2,......n,两个操作:1、修改第k个数字,2、查询区间[l,r]中与n互质的数之和。 解题思路:咱一看,像线段树,但是如果用线段树做,那么每个区间一定要记录所有的素因子,这样会超内存。然后我就做不来了。后来看了题解,原来是用容斥原理来做的。还记得这道题目吗?求区间[1,r]中与p互质的数的个数,如果不会的话就先去做那题吧。现在这题是求区间[l,r]中与n互质的数的和

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

poj 1287 Networking(prim or kruscal最小生成树)

题意给你点与点间距离,求最小生成树。 注意点是,两点之间可能有不同的路,输入的时候选择最小的,和之前有道最短路WA的题目类似。 prim代码: #include<stdio.h>const int MaxN = 51;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int P;int prim(){bool vis[MaxN];

poj 2349 Arctic Network uva 10369(prim or kruscal最小生成树)

题目很麻烦,因为不熟悉最小生成树的算法调试了好久。 感觉网上的题目解释都没说得很清楚,不适合新手。自己写一个。 题意:给你点的坐标,然后两点间可以有两种方式来通信:第一种是卫星通信,第二种是无线电通信。 卫星通信:任何两个有卫星频道的点间都可以直接建立连接,与点间的距离无关; 无线电通信:两个点之间的距离不能超过D,无线电收发器的功率越大,D越大,越昂贵。 计算无线电收发器D