protobuf文件嵌套结构实例

ProtoBuf实战用法 ProtoBuf学习 阅读详情

protobuf文件嵌套结构实例  

2013-08-22 14:10:49|  分类: 开源项目|举报|字号 订阅


class LogonReqMessage : public ::google::protobuf::MessageLite { 
public: 
LogonReqMessage(); 
virtual ~LogonReqMessage(); 
// implements Message ---------------------------------------------- 
//下面的成员函数均实现自MessageLite中的虚函数。 
//创建一个新的LogonReqMessage对象,等同于clone。 
LogonReqMessage* New() const; 
//用另外一个LogonReqMessage对象初始化当前对象,等同于赋值操作符重载(operator=) 
void CopyFrom(const LogonReqMessage& from); 
//清空当前对象中的所有数据,既将所有成员变量置为未初始化状态。 
void Clear(); 
//判断当前状态是否已经初始化。 
bool IsInitialized() const; 
//在给当前对象的所有变量赋值之后,获取该对象序列化后所需要的字节数。 
int ByteSize() const; 
//获取当前对象的类型名称。 
::std::string GetTypeName() const; 
// required int64 acctID = 1; 
//下面的成员函数都是因message中定义的acctID字段而生成。 
//这个静态成员表示AcctID的标签值。命名规则是k + FieldName(驼峰规则) + FieldNumber。 
static const int kAcctIDFieldNumber = 1; 
//如果acctID字段已经被设置返回true,否则false。 
inline bool has_acctid() const; 
//执行该函数后has_acctid函数将返回false,而下面的acctid函数则返回acctID的缺省值。 
inline void clear_acctid(); 
//返回acctid字段的当前值,如果没有设置则返回int64类型的缺省值。 
inline ::google::protobuf::int64 acctid() const; 
//为acctid字段设置新值,调用该函数后has_acctid函数将返回true。 
inline void set_acctid(::google::protobuf::int64 value); 
// required string passwd = 2; 
//下面的成员函数都是因message中定义的passwd字段而生成。这里生成的函数和上面acctid 
//生成的那组函数基本相似。因此这里只是列出差异部分。 
static const int kPasswdFieldNumber = 2; 
inline bool has_passwd() const; 
inline void clear_passwd(); 
inline const ::std::string& passwd() const; 
inline void set_passwd(const ::std::string& value); 
//对于字符串类型字段设置const char*类型的变量值。 
inline void set_passwd(const char* value); 
inline void set_passwd(const char* value, size_t size); 
//可以通过返回值直接给passwd对象赋值。在调用该函数之后has_passwd将返回true。 
inline ::std::string* mutable_passwd(); 
//释放当前对象对passwd字段的所有权,同时返回passwd字段对象指针。调用此函数之后,passwd字段对象 
//的所有权将移交给调用者。此后再调用has_passwd函数时将返回false。 
inline ::std::string* release_passwd(); 
private: 
... ... 
}; 

下面是读写LogonReqMessage对象的C++测试代码和说明性注释。 
复制代码 代码如下:
void testSimpleMessage() 
{ 
printf("==================This is simple message.================\n"); 
//序列化LogonReqMessage对象到指定的内存区域。 
LogonReqMessage logonReq; 
logonReq.set_acctid(20); 
logonReq.set_passwd("Hello World"); 
//提前获取对象序列化所占用的空间并进行一次性分配,从而避免多次分配 
//而造成的性能开销。通过该种方式,还可以将序列化后的数据进行加密。 
//之后再进行持久化,或是发送到远端。 
int length = logonReq.ByteSize(); 
char* buf = new char[length]; 
logonReq.SerializeToArray(buf,length); 
//从内存中读取并反序列化LogonReqMessage对象,同时将结果打印出来。 
LogonReqMessage logonReq2; 
logonReq2.ParseFromArray(buf,length); 
printf("acctID = %I64d, password = %s\n",logonReq2.acctid(),logonReq2.passwd().c_str()); 
delete [] buf; 
} 

三、嵌套message生成的C++代码 
enum UserStatus { 
OFFLINE = 0; 
ONLINE = 1; 
} 
enum LoginResult { 
LOGON_RESULT_SUCCESS = 0; 
LOGON_RESULT_NOTEXIST = 1; 
LOGON_RESULT_ERROR_PASSWD = 2; 
LOGON_RESULT_ALREADY_LOGON = 3; 
LOGON_RESULT_SERVER_ERROR = 4; 
} 
message UserInfo { 
required int64 acctID = 1; 
required string name = 2; 
required UserStatus status = 3; 
} 
message LogonRespMessage { 
required LoginResult logonResult = 1; 
required UserInfo userInfo = 2; //这里嵌套了UserInfo消息。 
} 
对于上述消息生成的C++代码,UserInfo因为只是包含了原始类型字段,因此和上例中的LogonReqMessage没有太多的差别,这里也就不在重复列出了。由于LogonRespMessage消息中嵌套了UserInfo类型的字段,在这里我们将仅仅给出该消息生成的C++代码和关键性注释。 
复制代码 代码如下:
class LogonRespMessage : public ::google::protobuf::MessageLite { 
public: 
LogonRespMessage(); 
virtual ~LogonRespMessage(); 
// implements Message ---------------------------------------------- 
... ... //这部分函数和之前的例子一样。 
// required .LoginResult logonResult = 1; 
//下面的成员函数都是因message中定义的logonResult字段而生成。 
//这一点和前面的例子基本相同,只是类型换做了枚举类型LoginResult。 
static const int kLogonResultFieldNumber = 1; 
inline bool has_logonresult() const; 
inline void clear_logonresult(); 
inline LoginResult logonresult() const; 
inline void set_logonresult(LoginResult value); 
// required .UserInfo userInfo = 2; 
//下面的成员函数都是因message中定义的UserInfo字段而生成。 
//这里只是列出和非消息类型字段差异的部分。 
static const int kUserInfoFieldNumber = 2; 
inline bool has_userinfo() const; 
inline void clear_userinfo(); 
inline const ::UserInfo& userinfo() const; 
//可以看到该类并没有生成用于设置和修改userInfo字段set_userinfo函数,而是将该工作 
//交给了下面的mutable_userinfo函数。因此每当调用函数之后,Protocol Buffer都会认为 
//该字段的值已经被设置了,同时has_userinfo函数亦将返回true。在实际编码中,我们可以 
//通过该函数返回userInfo字段的内部指针,并基于该指针完成userInfo成员变量的初始化工作。 
inline ::UserInfo* mutable_userinfo(); 
inline ::UserInfo* release_userinfo(); 
private: 
... ... 
}; 

下面是读写LogonRespMessage对象的C++测试代码和说明性注释。 
复制代码 代码如下:
void testNestedMessage() 
{ 
printf("==================This is nested message.================\n"); 
LogonRespMessage logonResp; 
logonResp.set_logonresult(LOGON_RESULT_SUCCESS); 
//如上所述,通过mutable_userinfo函数返回userInfo字段的指针,之后再初始化该对象指针。 
UserInfo* userInfo = logonResp.mutable_userinfo(); 
userInfo->set_acctid(200); 
userInfo->set_name("Tester"); 
userInfo->set_status(OFFLINE); 
int length = logonResp.ByteSize(); 
char* buf = new char[length]; 
logonResp.SerializeToArray(buf,length); 
LogonRespMessage logonResp2; 
logonResp2.ParseFromArray(buf,length); 
printf("LogonResult = %d, UserInfo->acctID = %I64d, UserInfo->name = %s, UserInfo->status = %d\n" 
,logonResp2.logonresult(),logonResp2.userinfo().acctid(),logonResp2.userinfo().name().c_str(),logonResp2.userinfo().status()); 
delete [] buf; 
} 

四、repeated嵌套message生成的C++代码 
message BuddyInfo { 
required UserInfo userInfo = 1; 
required int32 groupID = 2; 
} 
message RetrieveBuddiesResp { 
required int32 buddiesCnt = 1; 
repeated BuddyInfo buddiesInfo = 2; 
} 
对于上述消息生成的代码,我们将只是针对RetrieveBuddiesResp消息所对应的C++代码进行详细说明,其余部分和前面小节的例子基本相同,可直接参照。而对于RetrieveBuddiesResp类中的代码,我们也仅仅是对buddiesInfo字段生成的代码进行更为详细的解释。 
复制代码 代码如下:
class RetrieveBuddiesResp : public ::google::protobuf::MessageLite { 
public: 
RetrieveBuddiesResp(); 
virtual ~RetrieveBuddiesResp(); 
... ... //其余代码的功能性注释均可参照前面的例子。 
// repeated .BuddyInfo buddiesInfo = 2; 
static const int kBuddiesInfoFieldNumber = 2; 
//返回数组中成员的数量。 
inline int buddiesinfo_size() const; 
//清空数组中的所有已初始化成员,调用该函数后,buddiesinfo_size函数将返回0。 
inline void clear_buddiesinfo(); 
//返回数组中指定下标所包含元素的引用。 
inline const ::BuddyInfo& buddiesinfo(int index) const; 
//返回数组中指定下标所包含元素的指针,通过该方式可直接修改元素的值信息。 
inline ::BuddyInfo* mutable_buddiesinfo(int index); 
//像数组中添加一个新元素。返回值即为新增的元素,可直接对其进行初始化。 
inline ::BuddyInfo* add_buddiesinfo(); 
//获取buddiesInfo字段所表示的容器,该函数返回的容器仅用于遍历并读取,不能直接修改。 
inline const ::google::protobuf::RepeatedPtrField< ::BuddyInfo >& 
buddiesinfo() const; 
//获取buddiesInfo字段所表示的容器指针,该函数返回的容器指针可用于遍历和直接修改。 
inline ::google::protobuf::RepeatedPtrField< ::BuddyInfo >* 
mutable_buddiesinfo(); 
private: 
... ... 
}; 

下面是读写RetrieveBuddiesResp对象的C++测试代码和说明性注释。 
复制代码 代码如下:
void testRepeatedMessage() 
{ 
printf("==================This is repeated message.================\n"); 
RetrieveBuddiesResp retrieveResp; 
retrieveResp.set_buddiescnt(2); 
BuddyInfo* buddyInfo = retrieveResp.add_buddiesinfo(); 
buddyInfo->set_groupid(20); 
UserInfo* userInfo = buddyInfo->mutable_userinfo(); 
userInfo->set_acctid(200); 
userInfo->set_name("user1"); 
userInfo->set_status(OFFLINE); 
buddyInfo = retrieveResp.add_buddiesinfo(); 
buddyInfo->set_groupid(21); 
userInfo = buddyInfo->mutable_userinfo(); 
userInfo->set_acctid(201); 
userInfo->set_name("user2"); 
userInfo->set_status(ONLINE); 
int length = retrieveResp.ByteSize(); 
char* buf = new char[length]; 
retrieveResp.SerializeToArray(buf,length); 
RetrieveBuddiesResp retrieveResp2; 
retrieveResp2.ParseFromArray(buf,length); 
printf("BuddiesCount = %d\n",retrieveResp2.buddiescnt()); 
printf("Repeated Size = %d\n",retrieveResp2.buddiesinfo_size()); 
//这里仅提供了通过容器迭代器的方式遍历数组元素的测试代码。 
//事实上,通过buddiesinfo_size和buddiesinfo函数亦可循环遍历。 
RepeatedPtrField<BuddyInfo>* buddiesInfo = retrieveResp2.mutable_buddiesinfo(); 
RepeatedPtrField<BuddyInfo>::iterator it = buddiesInfo->begin(); 
for (; it != buddiesInfo->end(); ++it) { 
printf("BuddyInfo->groupID = %d\n", it->groupid()); 
printf("UserInfo->acctID = %I64d, UserInfo->name = %s, UserInfo->status = %d\n" 
, it->userinfo().acctid(), it->userinfo().name().c_str(),it->userinfo().status()); 
} 
delete [] buf; 
} 

【python】【protobuf】逆向还原protobuf结构 很多场景都有一个需求:得到了一个编码后的protobuf数据(比如竞品调研的的数据包),需要逆向还原其proto结构文件。从编码入手,人工肉眼分析。费时费力容易出错(在一些嵌套结构,或者有优化编码的地方)但,对理解 protobuf 编码原理非常有帮助借助 protoc.exe缺点:没有给出数据类型1 {1 {\351\014"2 {借助在线工具先把protobuf的基本结构识别出来,然后结合对数据的理解进行修正。为什么需要修正? 阅读详情

相关推荐

Protobuf逆向解析避坑指南:从二进制数据到.proto文件的完整流程

本文详细介绍了Protobuf逆向解析的完整流程,从二进制数据到.proto文件的精准还原。通过分析字段类型歧义、嵌套结构迷宫和特殊编码陷阱等核心挑战,提供工具链组合拳和类型推断的启发式方法论,帮助开发者高效完成Protobuf逆向工程。

weixin_29041767的博客 575

protobuf复杂场景下的使用,包含多层嵌套结构体,repeated等(六)

protobuf复杂场景使用,包含多层结构体嵌套,repeated等成员参数情况。

蜗牛的专栏 3349

protobuf(c++)设置嵌套类的值的两种方法(set_allocated_和mutable_的使用)

.proto 文件如下: syntax = "proto3"; package geomproto; message Geom{ Point2d p=1; } message Point2d{ double x=1; double y=2; } 设置Point2d成员的方式1: Geom geom; Point2d *tmp = new Point2d(); ...

鸟哥的博客 3418

Python 使用 Protobuf 的 message 嵌套,repeated 字段类型,google.protobuf.Any 字段类型,enum 枚举字段

phone.proto文件如下: syntax = 'proto3'; import "google/protobuf/any.proto"; package main; message User{ int32 index = 1; string name = 2; repeated Phone content = 3; google.protobuf.Any Value = 4; } message Phone{ string phoneType = 1;

星际跳跃的博客 5866

Linux中断子系统分析之(四):驱动程序申请中断

中断子系统中有一个重要的设计机制,那就是Top-half和Bottom-half,将紧急的工作放置在Top-half中来处理,而将耗时的工作放置在Bottom-half中来处理。 如果中断不分上下半部处理,那么意味着只有等上一个中断完成处理后才会打开中断,下一个中断才能得到响应。当某个中断处理处理时间较长时,很有可能就会造成其他中断丢失而无法响应,影响系统性能。 中断分成上下半部处理可以提高中断的响应能力,在上半部处理完成后便将中断打开,这样就可以响应其他中断了,等到中断退出的时候再进行下半部的处理。为了进

m0_46525308的博客 1225

datax web升级springboot3 jdk17

datax web但GitHub上还是springboot2,没有升级过,最近扫漏洞发现spring-core漏洞必须升级到6.x才能解决,这时不得不将springboot升级到3.x,随之而来是jdk、mybatis-plus等等的升级,调整了几天才没问题,痛苦的开发人生~~以上,有疑问欢迎留言。

liyinglong1023的博客 973

ProtoBuf(Google Protocol Buffers)—— repeated 修饰字段注意点(packed修饰)

ProtoBuf—— (repeated 修饰 )repeated1、定义2、使用事项参考 repeated 1、定义 repeated类型相当于STL的vector,可以用来存放N个相同类型的内容。 proto2 中还有 repeated 可选,在proto3 中则已经被摒弃并且默认格式为pack。 packed修饰只用于repeated字段 或 基本类型的repeated字段,用在其他字段,编译 .proto 文件时会报错 2、使用事项 repeated 修饰的字段有两种表达方式: messa

JMW1407的博客 6284

H3C IPsec over GRE VPN 实验

配置 IPsec over GRE VPN 来连通两端内网

M建的博客 2460

protoc-gen-star高级特性:处理复杂Protobuf类型和嵌套结构

protoc-gen-star(PG*)是一款强大的Protobuf插件库,专为高效的基于Protobuf的代码生成而设计。它提供了丰富的工具和API,帮助开发者轻松处理各种复杂的Protobuf类型和嵌套结构,大大简化了代码生成的过程。 ## 深入了解Protobuf复杂类型 Protobuf定义中包含多种复杂类型,如嵌套消息、枚举、map类型和oneof字段等。这些类型在实际应用中非常常见

gitblog_00309的博客 659

IC版图设计布局经验90条!

13 如果一个cell调用其它cell,被调用的cell的vssx,vddx,vssb,vddb如果没有和外层cell连起来,要打上PIN,否则通不过diva检查.尽量在布局低层cell时就连起来。48 在匹配电路的mos管左右画上dummy,用poly,poly的尺寸与管子尺寸一样,dummy与相邻的第一个poly gate的间距等于poly gate之间的间距。8 更改cell时查看路径,一定要在正确的library下更改,以防copy过来的cell是在其他的library下,被改错。

weixin_44606964的博客 910

Python爬取拼多多商品数据保姆级教程(附源码及效果图)

本文介绍了使用Python爬取拼多多商品数据的完整教程。通过DrissionPage库模拟浏览器操作,利用正则表达式提取嵌入在HTML中的商品数据(关键步骤是从window.rawData变量获取),解析后转换为结构化数据并导出Excel。教程包含八大步骤:环境配置、浏览器初始化、网络监听、搜索模拟、数据提取(核心是正则匹配JSON)、数据验证、字段解析和Excel导出,最后提供了封装好的函数可直接调用。该方法特别适合课程作业或毕业设计获取电商数据,能爬取商品名称、价格、销量等关键信息,处理了价格单位转换等

weixin_46449236的博客 2077

解放你的Protobuf数据:无需.proto文件也能轻松解码的终极方案

还在为没有.proto定义文件而无法解析Protobuf数据烦恼吗?🤔 面对那些神秘的二进制流,传统工具往往束手无策。但别担心,**protobuf-decoder** 正是为你量身打造的解决方案!这个强大的工具能够直接解码Protobuf二进制数据,无需任何原始schema文件,就能将晦涩的字节流转换为清晰易读的JSON格式。无论你是开发工程师、安全测试人员,还是数据处理专家,这款工具都能让你

gitblog_00426的博客 1078

《UDS协议从入门到精通》系列——图解0x27:安全访问

什么是安全访问服务?应用场景和基本原理是什么?全网最直观详细的图解UDS-0x27:安全访问服务!!

车载系统攻城狮 7231

ProtoBuf生成EmmyLua注解API提示文件(支持复杂的嵌套结构)

身为一个码农,写代码没有提示是最难受最影响效率的吧,偏偏lua就是这样的。目前,大多数的Unity游戏开发者都已经开始使用IntelliJ IDEA来写lua代码,很重要的一个原因就是IDEA中的EmmyLua插件(EmmyLua插件下载地址:https://emmylua.github.io/),使用这个插件可以极大的提高我们的开发效率。 我们自己写的业务逻辑添加emmylua注解很简单,但是如何在项目中生成带注解的proto提高我们的开发效率呢?这时我们就需要一个像导表工具一样的根据proto导出em

素颜悠悠的博客 3100

★教程1:matlab学习教程入门100例目录

★基础入门 1.为什么要学习MATLAB 2.MATLAB安装 持续更新....... ★MATLAB基础编程语言熟悉

FPGA/MATLAB学习教程/源码/项目合作开发 4万+

基于STM32F4XX 、HAL库的SHT40-CD1B-R3温湿度传感器驱动应用C语言程序设计

define SHT40_ADDR_READ 0x8B // CD1B 读地址 ((0x45 << 1) + 1)#define SHT40_ADDR_WRITE 0x8A // CD1B 写地址 (0x45 << 1)// 初始化 I2C1 (根据 CubeMX 生成的函数)// 湿度: -6%RH + 125%RH * (raw / 2^16)// 温度: -45°C + 175°C * (raw / 2^16)// 返回值: 0=成功, 1=失败(CRC错误或I2C通信错误)

PP_Cottage的博客 236

Protobuf 深度解析:从基础语法到高级应用

Protobuf 提供了一系列内置的基本类型(如stringint32bool等),同时也鼓励用户根据需求定义自己的结构类型。模块化设计:通过import拆分大型.proto文件,提升可维护性。结构复用:合理使用嵌套message和map灵活适配复杂数据需求。类型安全:通过枚举和标准库类型(如Timestamp)保障数据一致性。兼容性策略:字段编号管理和工具链支持确保系统长期演进。文档属性:Protobuf 文件本身具有良好的可读性,适合当作接口文档使用。

Landcc的博客 1844

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

protobuf安装和嵌套定义

背景 博主因为公司项目原因,客户端和服务端通信采用了protobuf协议,关于protobuf协议,不明白的自行百度,这个协议因其高效安全性,还是蛮常见的。 博主也是第一次安装使用,定义协议文件时发现不知道如何嵌套定义结构了,摸索。 安装 建议直接参考git上的README 下载https://github.com/google/protobuf,解压 需要以下依赖工具autoconf auto...

CTO技术的博客 1528

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

深入理解Protobuf的 .proto 文件结构与消息定义

在这个例子中,我们定义了一个名为Personnameid和email。每个字段都有一个唯一的字段编号(Field Number),这是 Protobuf 序列化时用来标识字段的关键信息。⚠️字段编号必须唯一且不能重复使用。通常从 1 开始递增,最大支持到 2^29 - 1。在本文中,我们深入探讨了.proto如何定义消息结构(message)各种字段规则(singular、repeated、map)支持的数据类型(int32、string、bytes 等)枚举(enum)和嵌套结构。

Landcc的博客 1274

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

终极指南:快速实现无proto文件的Protobuf数据解码

在现代数据交互场景中,Protobuf作为高效的序列化协议被广泛应用,但缺乏.proto定义文件时如何解析数据成为开发者的普遍痛点。protobuf-decoder正是为解决这一难题而生,它能直接解码二进制数据并转换为直观JSON格式,无需依赖原始schema文件,让数据调试、安全审计和迁移工作变得简单高效。 ## 🛠️ 快速上手:5分钟完成首次解码体验 想要体验protobuf-decod

gitblog_00202的博客 366

终极protobuf二进制解析指南:无需proto文件轻松解码

在协议开发和网络安全分析中,protobuf(Protocol Buffers)二进制数据的解析一直是个技术挑战。传统方法需要依赖.proto文件才能正确解码,但现实中往往面临协议文件缺失或加密的情况。protobuf-decoder正是为解决这一痛点而生,让您在没有.proto文件的情况下也能轻松解析protobuf二进制数据!🔍 ## 技术挑战:当.proto文件不可用时 protobu

gitblog_00610的博客 1036

Protobuf无定义文件处理终极方案:Blackbox Protobuf工作原理

Blackbox Protobuf 是一套无需匹配 protobuf 定义文件即可处理编码 Protocol Buffers(protobuf)的工具集,为开发者在没有原始 `.proto` 文件的情况下解析和操作 protobuf 数据提供了完整解决方案。无论是调试网络流量、分析第三方应用数据交互,还是逆向工程 protobuf 协议,Blackbox Protobuf 都能帮助用户快速获取结构

gitblog_00079的博客 254

Blackbox Protobuf完全指南:无需定义文件轻松解析Protobuf消息

Blackbox Protobuf是一套用于处理编码的Protocol Buffers(protobuf)的工具集,无需匹配的protobuf定义文件即可轻松解析和编辑Protobuf消息。本文将详细介绍如何使用Blackbox Protobuf的各项功能,帮助新手和普通用户快速上手这一强大工具。 ## 为什么选择Blackbox Protobuf? 在日常开发和调试中,我们经常会遇到需要处理

gitblog_00333的博客 581

protobuf.js与TypeScript完美融合:类型安全的Protobuf开发实践

你是否还在为JavaScript中Protobuf数据处理的类型错误而烦恼?是否希望在编译阶段就能捕获数据格式问题?本文将带你通过protobuf.js与TypeScript的无缝集成,构建类型安全的Protobuf开发流程,让数据交互从此告别"运行时惊喜"。 读完本文你将掌握: - 类型定义文件自动生成的完整流程 - 类型安全的消息序列化与反序列化 - 复杂嵌套结构的类型处理技巧 - 常见问题...

gitblog_00544的博客 1107

终极指南:无需.proto文件也能轻松解析Protobuf数据的完整方案

在当今数据驱动的开发环境中,Protobuf以其高效的序列化能力成为微服务通信的首选协议。然而,当你面对一堆二进制数据却没有对应的.proto定义文件时,解析工作就变得异常困难。protobuf-decoder正是为解决这一痛点而生,它能够直接解析Protobuf二进制数据并转换为直观的JSON格式,让数据解析工作变得简单高效。 ## 🔍 解析困境:当.proto文件缺失时的数据黑洞 **场

gitblog_00863的博客 526
上一篇: 使用protobuf定义消息
下一篇: 为Cocos2d-x的Android平台添加Protobuffer支持
linuxheik
博客等级 码龄15年 865粉丝 135原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值