Dynamically generate a protobuf message and return a pointer to it

First of all, I am not very good at C ++, so maybe I am observing something here. I am trying to dynamically generate protobuf messages from .proto files with the following code:

int init_msg(const std::string & filename, protobuf::Arena* arena, protobuf::Message** new_msg){
  using namespace google::protobuf;
  using namespace google::protobuf::compiler;

  DiskSourceTree source_tree;
  source_tree.MapPath("file", filename);

  MuFiErCo error_mist;
  Importer imp(&source_tree, &error_mist);

  printf("Lade Datei:%s \n", filename.c_str());

  const FileDescriptor* f_desc = imp.Import("file");

  const Descriptor* desc = f_desc->FindMessageTypeByName("TestNachricht");

  const Message* new_msg_proto = dmf.GetPrototype(desc);

  *new_msg = new_msg_proto->New(arena);

  //Debug
  cout << (*new_msg)->GetTypeName() << endl;

  return 0;
}

int main(int argc, char* argv[]){

  protobuf::Arena arena;

  protobuf::Message *adr2, *adr1;

  init_msg("schema-1.proto", &arena, &adr1);
  init_msg("schema-1.proto", &arena, &adr2);

  printf("MSG_Pointer: %p, %p\n", adr1, adr2);

  cout << adr1->GetTypeName() << endl;

  arena.Reset();

  return 0;
}    

I thought that if I use Arena, a new message will also be available outside of the function. But there is always segfault if I try to access a post. I assume this is a simple mistake, but I could not figure out how to solve this.

Here is the conclusion:

Lade Datei:schema-1.proto 
packet.TestNachricht
Lade Datei:schema-1.proto 
packet.TestNachricht
MSG_Pointer: 0x1b293b0, 0x1b287f0
Speicherzugriffsfehler (Speicherabzug geschrieben)
+4
source share
1 answer

, , , FileDescriptor . , init_msg , .proto. . . -

.

#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <memory>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/arena.h>


using namespace std;
using namespace google::protobuf;


class MuFiErCo : public compiler::MultiFileErrorCollector
{
public:
    void AddError(const string & filename, int line, int column, const string & message){
        printf("Err: %s\n", message.c_str());
    }
    void AddWarning(const string & filename, int line, int column, const string & message){
        printf("Warn: %s\n", message.c_str());
    }

};


compiler::Importer* init_proto_dir(Arena* arena, const std::string &root_dir){
    using namespace compiler;

    static DiskSourceTree source_tree;
    source_tree.MapPath("", root_dir);

    static MuFiErCo error_mist;
    static Importer* imp = Arena::Create<Importer>(arena, &source_tree, &error_mist);

    return imp;
}


void init_proto_def(compiler::Importer* imp, const std::string &proto_file){
    using namespace compiler;

    imp->Import(proto_file);

    return;
}


Message* init_msg(compiler::Importer* imp, Arena* arena, const std::string &msg_name){

    const DescriptorPool* pool = imp->pool();

    static DynamicMessageFactory dmf;

    const Descriptor* desc = pool->FindMessageTypeByName(msg_name);

    const Message* msg_proto = dmf.GetPrototype(desc);

    return msg_proto->New(arena);
}


int set_value(Message* msg, const char* value_name, unsigned long int value){
    const Message::Reflection* reflec = msg->GetReflection();
    const Descriptor* desc = msg->GetDescriptor();

    const FieldDescriptor* fdesc = desc->FindFieldByName(value_name);

    reflec->SetUInt64(msg, fdesc, value);

    return 0;

}


int main(int argc, char* argv[]){

    Arena arena;

    compiler::Importer* imp = init_proto_dir(&arena, "");
    init_proto_def(imp, "schema-1.proto");

    Message* msg = init_msg(imp, &arena, "packet.TestNachricht");

    set_value(msg, "zahl", 23434);

    cout << msg->DebugString() << endl;

    return 0;
}
+1

Source: https://habr.com/ru/post/1671046/


All Articles