c++ - 为什么我的 protobuf 反序列化给出了空的有效载荷?
问题描述
在带有 VS2017 的 Windows 上运行 protobuf 3.9.0,我试图在 C++ 中使用CodedOutputStream
和反序列化我的 protobuf 模型CodedInputStream
,但解码器总是给我一个空的结果。我使用长度前缀,可以从解码器端的流中读取大小。一个in-place encode/decode源码如下,其中Any
使用了message
import "google/protobuf/any.proto";
message Pouch {
google.protobuf.Any msg = 1;
}
bool EncodeDecode(google::protobuf::Message* pMeta, std::string& out_packet) {
//
// Encoding
//
// CAUTION:
// - Must dynamic allocate to avoid protobuf bug <SharedDtor crash #435>.
std::shared_ptr<Pouch> pPayload = std::make_shared<Pouch>();
google::protobuf::Any env;
env.PackFrom(*pMeta);
pPayload->set_allocated_msg(&env);
// Prefix with size
const int nTipBytes = 4;
int nBytesMsg = (int)pMeta->ByteSizeLong();
int nBytesPacket = nBytesMsg + nTipBytes;
out_packet.assign(nBytesPacket, '\0');
google::protobuf::io::ArrayOutputStream aos((void*)out_packet.c_str(), nBytesPacket);
google::protobuf::io::CodedOutputStream cos(&aos);
cos.WriteVarint32(nBytesMsg);
bool res = pMeta->SerializeToCodedStream(&cos);
printf("payload has message: %d\n", pPayload->has_msg());
//
// Decoding
//
Pouch out_pouch;
google::protobuf::io::ArrayInputStream ais(out_packet.c_str(), nBytesPacket);
google::protobuf::io::CodedInputStream cis(&ais);
google::protobuf::uint32 nPayloadBytes;
cis.ReadVarint32(&nPayloadBytes);
google::protobuf::io::CodedInputStream::Limit msgLimit = cis.PushLimit(nPayloadBytes);
res = out_pouch.ParseFromCodedStream(&cis);
cis.PopLimit(msgLimit);
printf("decoded payload has message: %d\n", out_pouch.has_msg());
pPayload->release_msg();
return res;
}
上面的代码打印出一个空类型的 URL
payload has message: 1
decoded payload has message: 0
但是大小前缀nPayloadBytes
给出了正确的数字。编码和解码的结果都是true
.
我哪里错了?
解决方案
您在编码时将任何类型的 pMeta 包写入 CodedOutputStream cos,并在解码时期待一个消息 Pouch。我认为你的意思是编码 pPayload 消息而不是 pMeta,它已经在它的 msg 字段中包含 pMeta 消息。用于测试的完整代码:
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/util/delimited_message_util.h>
#include "teste.pb.h"
#include <string>
bool EncodeDecode(google::protobuf::Message* pMeta, std::string& out_packet) {
//
// Encoding
//
// CAUTION:
// - Must dynamic allocate to avoid protobuf bug <SharedDtor crash #435>.
std::shared_ptr<Pouch> pPayload = std::make_shared<Pouch>();
google::protobuf::Any env;
env.PackFrom(*pMeta, "bob.bob.bob");
pPayload->set_allocated_msg(&env);
// Prefix with size
const int nTipBytes = 4;
int nBytesMsg = (int)pPayload->ByteSizeLong();
int nBytesPacket = nBytesMsg + nTipBytes;
out_packet.assign(nBytesPacket, '\0');
google::protobuf::io::ArrayOutputStream aos((void*)out_packet.c_str(), nBytesPacket);
google::protobuf::io::CodedOutputStream cos(&aos);
cos.WriteVarint32(nBytesMsg);
bool res = pPayload->SerializeToCodedStream(&cos);
printf("payload has message: %d\n", pPayload->has_msg());
//
// Decoding
//
Pouch out_pouch;
google::protobuf::io::ArrayInputStream ais(out_packet.c_str(), nBytesPacket);
google::protobuf::io::CodedInputStream cis(&ais);
google::protobuf::uint32 nPayloadBytes;
cis.ReadVarint32(&nPayloadBytes);
google::protobuf::io::CodedInputStream::Limit msgLimit = cis.PushLimit(nPayloadBytes);
res = out_pouch.ParseFromCodedStream(&cis);
cis.PopLimit(msgLimit);
printf("decoded payload has message: %d\n", out_pouch.has_msg());
if (out_pouch.has_msg()){
Sample s;
out_pouch.msg().UnpackTo(&s);
printf("value: %d\n", s.number());
}
pPayload->release_msg();
return res;
}
int main(){
Sample *mymsg = new Sample();
mymsg->set_number(5123);
std::string bigstring;
EncodeDecode(mymsg, bigstring);
}
和.proto:
syntax = "proto3";
import "google/protobuf/any.proto";
message Pouch {
google.protobuf.Any msg = 1;
}
message Sample {
int32 number = 1;
}
推荐阅读
- python - 当网站格式不同时如何接受空白
- javascript - 如何使用 javascript 中的 lambda 在 cognito 中以编程方式将用户添加到组?
- azure - 如何为 AKS 中的出口流量保留 pod IP 地址?
- batch-file - 是否可以转义可以在 .bat 中抛出的任何文件名的字符
- php - 如何使用基于 cookie 的身份验证从 REST API 获取用户
- amazon-ec2 - 在哪里可以找到带有 AWS EC2 实例的 AWS ECS 的日志?
- javascript - 在javascript中获取没有子内容的元素文本
- angular - 它成为分组日而不是月
- python - django访问urls.py的顺序是什么
- angular - Angular 材质样式问题