次のような PB を使用して RPC プロトコルを作成します。
enum EMessages {
E_MSG_METHOD_CONNECT = 0x8001,
E_MSG_EVENT_CONNECT = 0xA001,
...
}
struct MsgHeader {
required int32 sessionRef = 1;
required int32 transactionId = 2;
required int32 status = 3;
}
struct MSG_METHOD_CONNECT {
optional Messages opCode = 1 [default = E_MSG_METHOD_CONNECT];
required MsgHeader header = 2;
.. other fields ..
}
ここで、インターフェイスとテンプレート クラスを定義して、間接的なレベルを追加します。
class IMessage {
virtual INT getOpCode() = 0;
virtual STRING getName() = 0;
virtual size_t getSize() = 0;
virtual INT SerializeToString(STRING& out) = 0;
virtual INT ParseFromString(STRING& in) = 0;
....
}
template<class MESSAGE>
class IMessageImpl : public IMessage {
protected:
MESSAGE m_Message; ///< The Message Implementation
public:
virtual MESSAGE& getMessage() = 0;
};
そして、私はそれを次のように使用します:
IMessageImpl<MSG_METHOD_CONNECT> MsgConnect;
ここで、エンドポイントからデータを受信したら、もちろん、メッセージ opCode に従ってデータをデシリアライズする必要があります。この記事
を
読んで、boost::mpl::map のような型マップを使おうと思っていますが、使ったことがないので、いくつかの提案を探しています。
<< ------------------------ [編集] ---------------------- --- >>
上記のコードに関しては、次のようにコーディングしてみます。
template<class MESSAGE>
class PBMessage : public IMessageImpl<MESSAGE>
{
public:
PBMessage() {};
/* ... other methods ... */
};
// Map of types. The key is the Message opCode
typedef typename mpl::map< mpl::pair<mpl::int_[100], PBMessage<MSG_METHOD_CONNECT> >,
mpl::pair<mpl::int_[101], PBMessage<MSG_EVENT_CONNECT> >,
> TMessageMap;
// The Message type
template < typename MessageMap, int opCode >
typedef typename mpl::at<MessageMap, mpl::int_<opCode> >::type::value TMessage;
そして、受信したバッファからメッセージを作成するために、コーディングを試みます(疑似コードとして取り上げます):
class PBMessageFactory : public IMessageFactory {
public:
IMessage* createMessage(CHAR* buff, UINT size) {
int opCode = buff[0];
TMessage<TMessageMap, opCode> msg;
msg.ParseFromString( STRING(buff) );
}
};
しかし、成功しませんでした... mpl::map から型を取得する方法を提案してくれる人はいますか?
ありがとう、
ダニエレ。