2017-02-28 5 views
4

まず最初に、私はC++での経験はあまりないので、ここで何かを監督しています。 私は、動的に次のコードで.protoファイルからいるProtobufメッセージを生成しようとしている:私はアリーナを使用する場合、新しいメッセージが関数の範囲外でも利用可能であると思っ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", &arena, &adr2); 

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

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

    arena.Reset(); 

    return 0; 
}  

。 しかし、メッセージにアクセスしようとすると、常にセグメンテーションがあります。 それは単純なエラーだと思いますが、これを解決する方法を理解できませんでした。ここで

はouputを次のとおりです。

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

です定義。 'Importer'インスタンスを' main'に移動し、それを生き続ける必要があります。これはアリーナとは関係ありません。 –

+0

それは解決策でしたが、後で動作するコード例を提供します。 ありがとうございます! – LoopingLouie

答えて

1

問題は、私が思うに、 する方法と、新しく作成されたメッセージを残す init_msg戻ると、その.protoを調べる際のFileDescriptorらが破壊されていることです定義。 Importer インスタンスをメインに移動して、そのまま使用する必要があります。これは アリーナとは関係ありません。 - Igor Tandetnik

それが解決策でした。ここで

問題は、私が思うに、その.protoに質問する方法はありませんで、新しく作成されたメッセージを残すとき `init_msg`戻り、` FileDescriptor`らが破壊されていることであるいくつかの作業のコード例

#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; 
} 
+0

私は 'static'変数を使わない方が好きですが、このコード例は参考になります。ありがとう。 –

+0

私はしばらくの間、そのコードで動作しませんでしたが、静的変数は、LabViewのDLLとしての使用法から来たと思います。 気軽に拡張例を投稿してください。 – LoopingLouie

関連する問題