99

シリアル化してソケット接続を介して送信する必要があるオブジェクトの小さな階層があります。オブジェクトをシリアライズしてから、オブジェクトのタイプに基づいてデシリアライズする必要があります。C++ でこれを行う簡単な方法はありますか (Java にあるように)。

C++ シリアル化のオンライン コード サンプルまたはチュートリアルはありますか?

EDIT:明確にするために、オブジェクトをバイト配列に変換してからオブジェクトに戻す方法を探しています。ソケット送信はできます。

4

4 に答える 4

59

シリアライゼーションといえば、ブースト シリアライゼーション APIが思い浮かびます。シリアル化されたデータをネット経由で送信する場合は、Berkeley ソケットまたはasio ライブラリを使用します。

編集:
オブジェクトをバイト配列にシリアル化する場合は、次の方法でブースト シリアライザーを使用できます (チュートリアル サイトから取得)。

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
class gps_position
{
private:
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & degrees;
        ar & minutes;
        ar & seconds;
    }
    int degrees;
    int minutes;
    float seconds;

public:
    gps_position(){};
    gps_position(int d, int m, float s) :
    degrees(d), minutes(m), seconds(s)
    {}
};

実際のシリアル化は非常に簡単です。

#include <fstream>
std::ofstream ofs("filename.dat", std::ios::binary);

    // create class instance
    const gps_position g(35, 59, 24.567f);

    // save data to archive
    {
        boost::archive::binary_oarchive oa(ofs);
        // write class instance to archive
        oa << g;
        // archive and stream closed when destructors are called
    }

逆シリアル化も同様の方法で機能します。

また、ポインターのシリアル化 (トレスなどの複雑なデータ構造は問題ありません)、派生クラスを処理できるメカニズムもあり、バイナリとテキストのシリアル化を選択できます。さらに、すべての STL コンテナーがそのままサポートされています。

于 2009-02-07T14:57:04.210 に答える
16

場合によっては、単純型を扱うときに次のことができます。

object o;
socket.write(&o, sizeof(o));

概念実証または最初のドラフトとしては問題ないので、チームの他のメンバーは他の部分に取り組み続けることができます。

しかし、遅かれ早かれ、通常はすぐに、これはあなたを傷つけます!

次のような問題が発生します。

  • 仮想ポインター テーブルが破損します。
  • (データ/メンバー/関数への) ポインターが破損します。
  • 異なるマシンでのパディング/アライメントの違い。
  • ビッグ/リトル エンディアンのバイト順の問題。
  • float/double の実装のバリエーション。

(さらに、受信側で何に解凍するかを知る必要があります。)

これは、クラスごとに独自のマーシャリング/アンマーシャリング メソッドを開発することで改善できます。(理想的には仮想であり、サブクラスで拡張できます。) いくつかの単純なマクロを使用すると、さまざまな基本型をビッグ/リトル エンディアン ニュートラルな順序で非常に迅速に書き出すことができます。

しかし、そのような単調な作業は、 boost のシリアライゼーション ライブラリを介して処理する方がはるかに優れており、より簡単です。

于 2009-02-07T15:17:36.027 に答える
1

学習のために、単純な C++11 シリアライザーを作成しました。私は他のさまざまなより重い製品を試しましたが、最新のg ++​​でうまくいかなかったりコンパイルに失敗したときに実際に理解できるものが欲しかったです(Cerealで私に起こりました;本当に素晴らしいライブラリですが複雑で、理解できませんでしたアップグレード時にコンパイラがスローしたエラー。)とにかく、それはヘッダーのみであり、POD タイプ、コンテナー、マップなどを処理します...バージョン管理はなく、保存されたのと同じアーキテクチャからファイルのみをロードします。

https://github.com/goblinhack/simple-c-plus-plus-serializer

使用例:

#include "c_plus_plus_serializer.h"

static void serialize (std::ofstream out)
{
    char a = 42;
    unsigned short b = 65535;
    int c = 123456;
    float d = std::numeric_limits<float>::max();
    double e = std::numeric_limits<double>::max();
    std::string f("hello");

    out << bits(a) << bits(b) << bits(c) << bits(d);
    out << bits(e) << bits(f);
}

static void deserialize (std::ifstream in)
{
    char a;
    unsigned short b;
    int c;
    float d;
    double e;
    std::string f;

    in >> bits(a) >> bits(b) >> bits(c) >> bits(d);
    in >> bits(e) >> bits(f);
}

于 2019-09-09T00:31:19.313 に答える