2017-02-28 63 views
4

首先,我對C++並不是很有經驗,所以也許我在這裏監督着某些東西。 我試圖動態生成的protobuf用下面的代碼從.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", &arena, &adr2); 

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

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

    arena.Reset(); 

    return 0; 
}  

我想如果我使用競技場,新的信息也可從功能範圍之外。 但是,如果我嘗試訪問消息,總會有一個段錯誤。 我想這是一個簡單的錯誤,但我無法弄清楚,如何解決這個問題。

這裏是輸出中:

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

這個問題,我認爲,是'FileDescriptor'等被破壞的時候'init_msg'回報,使新創建的消息,沒有辦法詢問其.proto定義。您需要將'Importer'實例移動到'main'並保持活動狀態。這與競技場無關。 –

+0

這就是解決方案,我將在稍後提供一個工作代碼示例。 非常感謝! – LoopingLouie

回答

1

的問題,我想,是的FileDescriptor等被破壞時 init_msg回報,沒有辦法離開新創建的消息發送到 詢問其.proto定義。您需要將Importer 實例移動到main並保持活動狀態。這與 賽場無關。 - 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: %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

我寧願不使用靜態變量,但這個示例代碼很有幫助。謝謝。 –

+0

我沒有在那段代碼上工作了一段時間,但我認爲靜態變量來自用法,作爲LabView的DLL。 隨意發佈增強示例。 – LoopingLouie

相關問題