(2009.5.11 新規作成。2011.8 加筆、新規公開。)
C++オブジェクトをネットワーク経由などでやり取りしたりするための、直列化 (シリアライズ) について。
概要
Windows向けにC++で開発する場合、MFC (Microsoft Foundation Classes) にはシリアライズ機能が含まれます。
boostにもポータブルなシリアリゼーション機能があり、MFCが利用できない場合、これが使えます。
クラス定義
直列化したいオブジェクトのクラスで、次のようにします。
C++
- #include <list>
- #include <string>
-
-
- #include <boost/serialization/version.hpp>
- #include <boost/serialization/split_member.hpp>
-
- class BusStop;
-
- class BusRoute {
-
- friend class boost::serialization::access;
- BOOST_SERIALIZATION_SPLIT_MEMBER()
-
- std::list<BusStop*> stops;
- std::string driver_name;
-
-
- template <class Archive>
- void save(Archive& ar, unsigned int version) const {
- ar & driver_name;
- ar & stops;
- }
-
-
- template <class Archive>
- void load(Archive& ar, unsigned int version) {
- if (version > 0)
- ar & driver_name;
- ar & stops;
- }
- };
-
- BOOST_CLASS_VERSION(BusRoute, 1)
何か特定のクラスのサブクラスにする必要はありません。save()
, load()
を定義するのと、いくつかのおまじないを書きます。
save(), load() では、最初の引数としてアーカイブなどが渡されます。&
演算子で追記、または読み込みを行います。
また、version も引数として渡されるため、それによって保存、再生する内容を変えることもできます。
オブジェクトの保存
オブジェクトを保存するには、boost::archive::binary_oarchive などのアーカイブクラスを通じて、ストリームに書き込みます。
例えば、シリアライズ可能な型Typのオブジェクトobjを受け取って、シリアライズし、MPIで送信するコードは、次のようになります。
C++
- template <typename Typ>
- void isend_obj( int dest_node, int tag, const Typ& obj,
- std::vector<MPI_Request>* reqs )
- {
- std::ostringstream oss;
- boost::archive::binary_oarchive oa(oss);
-
- oa << obj;
-
- int32_t len = oss.str().size();
- printf("len = %d\n", len);
- MPI_Request req;
- mMPI_CHECK_RESULT( MPI_Isend(&len, 1, MPI_INT32_T, dest_node, tag,
- MPI_COMM_WORLD, &req) );
- reqs->push_back(req);
- mMPI_CHECK_RESULT( MPI_Isend((void*) oss.str().data(), len, MPI_BYTE,
- dest_node, tag + 1, MPI_COMM_WORLD, &req) );
- reqs->push_back(req);
- }
アーカイブクラスは仲立ちをし、シリアライズされたデータはストリームに書き込まれます。
ライブラリとのリンク
boostのシリアライズ機能は、それだけで一つのライブラリとのリンクが必要です。リンカに -lboost_serialization オプションを加えます。
外部リンク