找回密码
 立即注册
查看: 258|回复: 1

Puerts使用google-protobuf的一些弯路

[复制链接]
发表于 2023-9-8 10:20 | 显示全部楼层 |阅读模式
简介:

       这里说下总结:puerte是可以使用protobufjs库或者google-protobuf来使用pb的,两者略有分歧,但是都能成功使用pb,protobufjs相对来说还要改削生成的pb文件,也就是需要改削require(protobuf.js)和引入Long,这个就直接导致我选择了google-protobuf
内容:

在ts代码中,如何使用protobuf,是研究了斗劲久的一个东西,在研究过程中,先后经历了
1. 上手protobufjs->发现为了可以使用,必需每次都去改削生成的pb文件,发下大佬之前的教程链接:Justin:Puerts中使用protobuf

2. 然后搞了半天,可以自动改削生成的js的require(”protobuf.js”),通过在生成脚本中使用:
call pbjs --dependency protobuf -t static-module -w commonjs -o B.js B.proto
通过dependency这个,强行把require里边的变量改为protobuf。

3. 使用的时候,发现接口出格不好用,不会使用,当然ts代码也不熟。转而发现google提供了官方的pb生成js的代码,那么官方是不是有更好的撑持呢?

4. 测验考试使用google,进而使用js版本的pb可以成功编码转码,然后使用c++版本的,发现UE4中不能使用上个版本的c++,,不能使用的原因是因为编译出来的descriptor_table总是不能通过编译,无法讲8进制转成10进制,发现最新的protobuf源码解决了这个问题,然后github上更新最新的protobuf源码,学习使用了cmake。配置如下。



5. 成功编译出了protobuflib和protoc几个文件。然后测验考试两者c++和js通信。C++要包含对应lib文件和对应的头文件:
        PublicIncludePaths.Add(Path.Combine(this.ModuleDirectory, ”../../Protobuf/”));

        PublicLibraryPaths.Add(”../Protobuf/”);
        PublicAdditionalLibraries.Add(”libprotobufd.lib”);
6. 通干预干与大佬,知道协议使用BufferArray,作为两者之间传输的媒介。
static void SendData(FArrayBuffer pkData);
DECLARE_DYNAMIC_DELEGATE_OneParam(FProcessMessage, FArrayBuffer, pkData);
7. 俄然发现两protobufjs和google-protobuf两者因为number最大值的问题,都不能很好的使用unit64定义的数值。网络提供了protobufjs的方案:Justin:Puerts中使用protobuf,还是测验考试用回protobufjs。protobufjs是通过引用Long库,把uint64位转化为Long类型,在解码和编码的时候就不会丢掉精度了,发下本身的pb文件和代码:
syntax = ”proto3”;

message ChangeInfo {
        uint32 changeType                        = 1;
        uint64 changeValue                        = 2;
}

message AwesomeMessage {
    string awesome_field = 1;
        int32 serverIdx                = 2;
        uint32 zoneId                = 3;
        uint64        player_id                        = 4;         
        repeated ChangeInfo changeInfo                        = 5;
}然后生成对应的js和ts代码,下面是如果调用,如果使用的数值未超过number,建议直接对player赋值,如果超过,就必需用Long,否则颠末encode编码后,精度会丢掉。
console.log(”hello, world”);

let aw = PB.AwesomeMessage.create();
aw.playerId = Long.fromString(”1234567891234567891”);
aw.serverIdx = 1000;
let wri:protobuf.Writer = PB.AwesomeMessage.encode(aw);
let byte:Uint8Array = wri.finish();

console.log(byte);

let redMes:PB.AwesomeMessage = PB.AwesomeMessage.decode(byte);
console.log((redMes.playerId as Long).toString());
console.log(redMes.playerId);
console.log(redMes.serverIdx);
8. 按照方案,成功弄出来了,但是在查看issiu的时候,发现居然有人成功从protobufjs转到了google-protobuf,https://github.com/protobufjs/protobuf.js/issues/1327,然后知道本来google也是可以撑持protobuf的,然后研究成功在里边增加了uint64 player_id = 4 [jstype = JS_STRING]; 能够成功转换。采用的强行把标识表记标帜为string的uint64位转为string,在编解码的时候也不会丢掉精度。
var hh = require(”./pb/Common_pb”);
var hhe = new hh.AwesomeMessage();

hhe.setPlayerId(”123456789123456789”);
hhe.setServeridx(1000);

console.log(hhe.getPlayerId());
console.log(hhe.getServeridx());

var bytes:Uint8Array = hhe.serializeBinary();

var hhd = hh.AwesomeMessage.deserializeBinary(bytes);
9. 进而发现了有两个开源项目是可以为google-protobuf生成.d.ts代码的,一个插件是 proto-gen-ts,一个插件是protoc-gen-grpc-web, 后者对uint64位撑持的更好一点。
proto-gen-ts:
set PROTOC_GEN_TS_PATH=”..\\..\\node_modules\\.bin\\protoc-gen-ts.cmd”

set OUT_DIR=”./generated”

..\protoc.exe --js_out=import_style=commonjs,binary:. Common.proto
..\protoc.exe --plugin=protoc-gen-ts=%PROTOC_GEN_TS_PATH2% --ts_out=./ Common.protoproto-gen-grpc-web:
PROTOC_GEN_TS_PATH=”..\\..\\node_modules\\.bin\\protoc-gen-grpc-web.cmd”

../protoc.exe Common.proto \
  --js_out=import_style=commonjs,binary:./ \
  --plugin=protoc-gen-grpc-web=$PROTOC_GEN_TS_PATH --grpc-web_out=import_style=typescript,mode=grpcweb:./

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2023-9-8 10:21 | 显示全部楼层
写的很详细,感谢分享
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-4-29 10:01 , Processed in 0.122113 second(s), 27 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表