加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 动态生成protobuf消息并返回指向它的指针

发布时间:2020-12-16 07:20:39 所属栏目:百科 来源:网络整理
导读:首先,我对C不是很有经验,所以也许我在这里监督一些事情. 我正在尝试使用以下代码从.proto文件动态生成protobuf消息: int init_msg(const std::string filename,protobuf::Arena* arena,protobuf::Message** new_msg){ using namespace google::protobuf; us
首先,我对C不是很有经验,所以也许我在这里监督一些事情.
我正在尝试使用以下代码从.proto文件动态生成protobuf消息:

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",&adr2);

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

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

  arena.Reset();

  return 0;
}

我想如果我使用Arena,新的Message也可以在函数范围之外使用.
但是如果我尝试访问Message,总会出现段错误.
我想这是一个简单的错误,但我无法弄清楚,如何解决这个问题.

这是输出:

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

解决方法

The problem,I think,is that FileDescriptor et al are destroyed when
init_msg returns,leaving the newly created message with no way to
interrogate its .proto definition. You’d need to move Importer
instance to main and keep it alive. This has nothing to do with
arenas. – Igor Tandetnik

那就是解决方案.

这是一些工作示例代码

#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: %sn",message.c_str());
    }
    void AddWarning(const string & filename,const string & message){
        printf("Warn: %sn",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,"packet.TestNachricht");

    set_value(msg,"zahl",23434);

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

    return 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读