c++ - 为什么我的 protobuf 反序列化给出空负载?

标签 c++ protocol-buffers

使用 VS2017 在 Windows 上运行 protobuf 3.9.0,我尝试使用 C++ 中的 CodedOutputStreamCodedInputStream 序列化和反序列化我的 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/

相关文章:

c++ - 左尖括号解释为 operator< 而不是模板参数

node.js - 如何获取protobuf.js以输出枚举字符串而不是整数

protocol-buffers - 多个原型(prototype)中的文件选项扩展

c++ - 在 GRPC 中使用字节数组 (cpp)

c# - 从 proto 文件构建 cs 文件?

c++ - 如何在 ubuntu 12.10 中隐藏 g++ c++11 编译警告

c++ - 使用 DT_CALCRECT 的 LPD3DXFONT DrawText?

C++ 从包含其名称的 char * 调用函数

c++ - 替换函数 'operator new' 无法声明 'inline' [-Werror,-Winline-new-delete]

protocol-buffers - Google protobuf 3 : deprecated a field, 但无法删除依赖项?