2010-08-11 165 views
4

我有一個C++程序發出各種事件,例如, StatusEventDetectionEvent與消息服務(當前活動MQ,通過activemq-cpp APU)不同的協議消息定義。我想寫一個接收這些消息的消息監聽器,解析它們並將它們寫入cout,以用於調試目的。聽衆有status_event_pb.hdetection_event_pb.h鏈接。協議緩衝區多態性

我的問題是:如何解析接收的事件而不知道它的類型?我想這樣做(在僞代碼)

receive event 
type = parseEventType(event); 
if(type == events::StatusEventType) { 
    events::StatusEvent se = parseEvent(event); 
    // do stuff with se 
} 
else { 
    // handle the case when the event is a DetectionEvent 
} 

我看着this question但我不知道,如果擴展是去這裏的正道。一個簡短的代碼片段指出的方式將不勝感激。 protobuf上的例子非常罕見!

謝謝!


看起來擴展確實是要走的路,但我有最後一點要清理。這裏的原始定義,我到目前爲止有:

// A general event, can be thought as base Event class for other event types. 
message Event { 
    required int64 task_id = 1;  
    required string module_name = 2; // module that sent the event 

    extensions 100 to 199;    // for different event types 
} 

// Extend the base Event with additional types of events. 
extend Event { 
    optional StatusEvent statusEvent = 100; 
    optional DetectionEvent detectionEvent = 101; 
} 

// Contains one bounding box detected in a video frame, 
// representing a region of interest. 
message DetectionEvent { 
    optional int64 frame = 2; 
    optional int64 time = 4; 
    optional string label = 6; 
} 

// Indicate status change of current module to other modules in same service. 
// In addition, parameter information that is to be used to other modules can 
// be passed, e.g. the video frame dimensions. 
message StatusEvent { 
    enum EventType { 
     MODULE_START = 1; 
     MODULE_END = 2; 
     MODULE_FATAL = 3; 
    } 
    required EventType type = 1;   
    required string module_name = 2; // module that sent the event 

    // Optional key-value pairs for data to be passed on. 
    message Data { 
     required string key = 1; 
     required string value = 2; 
    } 
    repeated Data data = 3; 
} 

我現在的問題是:(1)如何知道哪些特定的事件,該事件消息包含和(2)確保它僅包含一個這樣的事件(根據定義,它可以包含StatusEventDetectionEvent)。

+0

的protobuf的消息中找到這個有趣的螺紋:http://markmail.org/ message/dgmf5iuhhgoe7keb#query:protocol%20buffer%20polymorphism + page:1 + mid:73p5kddhvmokcpvo + state:results – recipriversexclusion 2010-08-11 17:06:48

+1

[可以使用協議緩衝區做多態的正確方法是什麼?](http://stackoverflow.com/q/3018743/1468366) – MvG 2013-02-25 13:11:41

回答

3

我不會使用協議緩衝區,但這可能是少用和其他習慣的組合。

無論如何,我想我會在這裏使用一個抽象類,以減輕一般處理和包含路由信息。不會使用protobuf定義的類,並且會包含protobuf消息。

class Message 
{ 
public: 
    Type const& GetType() const; 

    Origin const& GetOrigin() const; 
    Destination const& GetDestination() const; 

    // ... other informations 

    template <class T> 
    void GetContent(T& proto) const 
    { 
    proto.ParseFromIstream(&mContent); // perhaps a try/catch ? 
    } 

private: 
    // ... 

    std::stringstream mContent; 
}; 

通過這樣的結構,你必須在你的指尖一般和具體處理:

void receive(Message const& message) 
{ 
    LOG("receive - " << message.GetType() << " from " << message.GetOrigin() 
        << " to " << message.GetDestination()); 

    if (message.GetType() == "StatusEvent") 
    { 
    StatusEvent statusEvent; 
    message.Decode(statusEvent); 
    // do something 
    } 
    else if (message.GetType() == "DetectionEvent") 
    { 
    DetectionEvent detectionEvent; 
    message.Decode(detectionEvent); 
    // do something 
    } 
    else 
    { 
    LOG("receive - Unhandled type"); 
    } 
} 

當然,如果你使用的std::unordered_map<Type,Handler>而不是硬編碼if/else if +/else鏈那就更漂亮,但原理是相同的:

  1. 編碼在標頭中發送的消息的類型
  2. 僅解碼在接收和發送報頭基於這種類型
  3. 解碼中的代碼的一部分,其中所述類型是靜態已知
+0

感謝您的回答Matthieu。由於我需要protobuf系統的其他約束。隨着我對這項技術的瞭解越來越多,它看起來越好。我強烈推薦它。 – recipriversexclusion 2010-08-12 14:39:58

+0

@recipriversexclusion:沒有約束我們會是什麼:)?不幸的是,我不知道語法本身有一個「替代」。我想我只是通過定義不允許兩者出現的編碼器/解碼器來繞過這個問題。 – 2010-08-13 06:23:51