2010-08-11 172 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