protobuf菜鸟教程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了protobuf菜鸟教程相关的知识,希望对你有一定的参考价值。

参考技术A 一:环境安装

1 安装brew

ruby -e "$(curl -fsSL  https://raw.githubusercontent.com/Homebrew/install/master/install)"

2 使用brew安装protobuf

brew install protobuf

3 查看protoc版本

protoc --version

4 查看protobuf版本

brew search protobuf

二:示例

gps_data.proto

syntax = "proto3";

option java_package = "com.dongwt.proto";

message gps_data

int64 id = 1;

string terminalId = 2;

string dataTime = 3;

double lon = 4;

double lat = 5;

float speed = 6;

int32 altitude = 7;

int32 locType = 8;

int32 gpsStatus = 9;

float direction = 10;

int32 satellite = 11;



执行命令

protoc -I=src/main/resources/proto --java_out=src/main/java gps_data.proto

三:pom依赖(版本号序号protoc版本保持一致)

<dependency>

    <groupId>com.google.protobuf</groupId>

    <artifactId>protobuf-java</artifactId>

    <version>3.17.3</version>

</dependency>

四:单侧

public class TestGpsProtobuf

public static void main(String[] args)

System.out.println("===== 构建一个GPS模型开始 =====");

        GpsData.gps_data.Builder gps_builder = GpsData.gps_data.newBuilder();

        gps_builder.setAltitude(1);

        gps_builder.setDataTime("2017-12-17 16:21:44");

        gps_builder.setGpsStatus(1);

        gps_builder.setLat(39.123);

        gps_builder.setLon(120.112);

        gps_builder.setDirection(30.2F);

        gps_builder.setId(100L);

        GpsData.gps_data gps_data = gps_builder.build();

        System.out.println(gps_data.toString());

        System.out.println("===== 构建GPS模型结束 =====");

        System.out.println("===== gps Byte 开始=====");

        for(byte b : gps_data.toByteArray())

System.out.print(b);

       

System.out.println("\n" +"bytes长度" + gps_data.toByteString().size());

        System.out.println("===== gps Byte 结束 =====");

        System.out.println("===== 使用gps 反序列化生成对象开始 =====");

        GpsData.gps_data gd =null;

        try

gd = GpsData.gps_data.parseFrom(gps_data.toByteArray());

        catch (InvalidProtocolBufferException e)

e.printStackTrace();

       

System.out.print(gd.toString());

        System.out.println("===== 使用gps 反序列化生成对象结束 =====");

   

教程|如何在Cocos中完美使用protobuf.js

感谢『简书 ID: danniszhang』友情提供

http://www.jianshu.com/p/c4b8a8e3077f


最近正逢出来,社区许多人发帖强烈建议出个教程介绍「如何在Cocos中完美使用protobuf.js」。于是C姐开始深度挖坟,终于找到张晓衡同学上个月发布的这篇文章。征得本人同意后,现将教程发出来和小伙伴们共享。


初始化package.json文件

新建Cocos-JS或Creator项目,在项目根目录使用npm init命令,一路回车,在当前目录创建package.json文件用于nodejs三方模块的管理。关于npm的使用细节网络上有很多教程,在此不细说。


protobuf.js模块


我从Cocos2d-x时代就开始用protobuf.js模块来操纵protobuf,此方法在Cocos CreatorCocos2d-JS同样适用。


安装protobuf.js到项目

教程|如何在Cocos中完美使用protobuf.js

注意我们这里使用的是protobuf.js 5.x版本。 虽然protobuf.js目前最新的6.x版本,提供了ts、rpc等功能的支持,但接口变化太大,目前我还不熟练。


安装protobuf.js到全局

教程|如何在Cocos中完美使用protobuf.js

使用npm install -g参数将模块安装到全局,主要是方便使用protobuf.js提供的pbjs命令行工具。pbjs可以将proto原文件转换成json、js等,以提供不同的加载proto方式,我们可以根据自己的实际情况选择使用。


protobuf.js用法


下面是demo中定义的Player.proto文件内容

教程|如何在Cocos中完美使用protobuf.js

关于proto具体语法细节这里就不多说了,我们重点介绍如何将Player.proto文件中定义的Player对象在JS中实例化、属性赋值、序列化、反序列化操作。


静态语言中使用proto文件

在c++/java这类静态语言中使用protobuf通常是使用官方提供的protoc命令将proto文件编译成c++/java代码,像下面这样:

教程|如何在Cocos中完美使用protobuf.js

将输出路径的文件导入对应语言的工程中使用。


在Creator中使用proto文件

Javascript是动态语言,可以在运行时产生对象,因此protobuf.js提供了更为便捷的动态编译,将proto文件中的对象生成JS对象,下面简要讲解一下在Creator中具体的使用步骤:

1.加载proto文件并编译生成proto对象

教程|如何在Cocos中完美使用protobuf.js


2.实例化proto对象与属性赋值

教程|如何在Cocos中完美使用protobuf.js

build函数返回值PB对象中包含的是在proto中定义所有message对象,现在已经成为JS对象,可以被实例化,代码如下:

教程|如何在Cocos中完美使用protobuf.js


3.proto对象的序列化与反序列化

直接上代码

教程|如何在Cocos中完美使用protobuf.js


目前只能在web上使用protobuf,如果你非要把代码在JSB环境运行,悲催的事情就会发生。


拯救Cocos-JSB上的protobuf.js


为什么在原生上运行就挂掉了呢?要理解这个问题需要对nodejs、浏览器、Cocos-JSB这三个Javascript的运行宿主环境有一定的了解。


我之前的文章提到过在选择nodejs模块时,要注意是否同时支持nodejs和web,只要是纯JS的模块在Cocos中一般都可以随便用,比如async、undersocre、lodash等。


protobuf.js这个模块是可以很好的在浏览器和nodejs环境上运行的。但运行在Cocos-JSB上就会出问题。


首先我们要定位到出问题的关键代码:

教程|如何在Cocos中完美使用protobuf.js


问题分析

从protobuf.protoFromFile函数名看就知道是要进行文件加载。因此涉及到文件操作的API,我们来整理一下不同平台上的文件接口:

教程|如何在Cocos中完美使用protobuf.js

看到这里相信很多人已经明白为什么在Cocos-JSB上会有问题了,我们再来读一下protobuf.js源码,证实分析。


分析protobuf.js源码

找到protobuf.js加载文件的主要代码。

我为源码加上了注释,请认真读一下注释内容:

教程|如何在Cocos中完美使用protobuf.js

教程|如何在Cocos中完美使用protobuf.js


从上面的代码可以看出protobuf.js库是为浏览器和nodejs准备的,根本就没考虑过Cocos-JSB的存在。所以要在Cocos-JSB中使用protobuf.js其中的一个办法就是修改protobuf.js的源码,如下:

教程|如何在Cocos中完美使用protobuf.js


我们用Cocos的接口将代码修改一下,加载问题就被化解了,但问题真的解决了吗?除了上面代码外还有一处代码需要修改,源码如下:

教程|如何在Cocos中完美使用protobuf.js

这里我就不再贴修改码了,大家自行解决。


为protobuf.js继续填坑


写到这里,问题大多已经解决了。 但此时,如果你满怀信心地使用改造后的protobuf.js源码,当代码运行起来那一刻,我相信绝大多数人会一脸蒙逼。


了解Creator动态加载资源的方法

请大家思考一个问题,Creator项目中的一张图片,在web与Cocos-JSB上的文件路径会一样吗?直接使用protobuf.protoFromFile('xxx.proto')去加载一个proto文件能成功吗?


Cocos文档中说过要动态加载图片资源需要将文件存放在assets/resources目录下,使用如下方法加载:

教程|如何在Cocos中完美使用protobuf.js


可以尝试将proto文件存放在resources/pb/目录下,使用以下代码:

教程|如何在Cocos中完美使用protobuf.js

但同样会得到失败的提示,如何才能获得正确的资源路径呢?


cc.url.raw这个函数在浏览器、模拟器、手机上会返回不同的资源路径,这才是真正的资源路径,现在代码终于可以正常运行起来了。


更好的解决办法

我一直在探索Cocos H5正确的开发方式,虽然通过修改protobuf.js源码的方法可以解决Cocos-JSB上运行的问题,但这并不是唯一的解决方案。也希望有相关问题待解决的小伙伴可以开动脑路,提出更完美的解决方案。


Github编写了另一个和上述方法截然不同的方案,感兴趣的可以戳「阅读原文」进行参考并权衡优劣。

以上是关于protobuf菜鸟教程的主要内容,如果未能解决你的问题,请参考以下文章

Google Protobuf简明教程

Google Protobuf简明教程

golang 使用 protobuf 的教程

咸鱼教程protobuf在websocket通讯中的使用

教程|如何在Cocos中完美使用protobuf.js

Google Protobuf简明教程