为什么我的 protobuf 反序列化给出空负载?
Why is my protobuf deserialization giving empty payload?
运行 protobuf 3.9.0 on Windows with VS2017,我正在尝试在 C++ 中使用 CodedOutputStream
和 CodedInputStream
序列化和反序列化我的 protobuf 模型,但是解码器总是给我一个空的结果。我使用长度前缀,可以从解码器端的流中读取大小。一个就地encode/decode源码如下,其中使用了Any
消息
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, '[=11=]');
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, '[=10=]');
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;
}
运行 protobuf 3.9.0 on Windows with VS2017,我正在尝试在 C++ 中使用 CodedOutputStream
和 CodedInputStream
序列化和反序列化我的 protobuf 模型,但是解码器总是给我一个空的结果。我使用长度前缀,可以从解码器端的流中读取大小。一个就地encode/decode源码如下,其中使用了Any
消息
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, '[=11=]');
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, '[=10=]');
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;
}