使用 VS2017 在 Windows 上运行 protobuf 3.9.0,我尝试使用 C++ 中的 CodedOutputStream
和 CodedInputStream
序列化和反序列化我的 protobuf 模型,但解码器总是给出我的结果是空的。我使用长度前缀,可以从解码器端的流中读取大小。就地编码/解码源代码如下,其中使用了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, '\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;
}
关于c++ - 为什么我的 protobuf 反序列化给出空负载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58962185/