web-dev-qa-db-ja.com

Cでのデータ構造のシリアル化

データ構造をディスクにシリアル化して、後で再度読み込むことができるCライブラリが欲しいのですが。ネストされた構造を任意に受け入れる必要があり、循環参照が含まれる可能性があります。

このツールには、私のデータ構造を記述する構成ファイルが必要だと思います。ライブラリはコード生成の使用を許可されていますが、それなしでこれを実行することは可能だとかなり確信しています。

データの移植性には興味がありません。キャッシュとして使いたいので、環境が変わらなくても大丈夫です。

ありがとう。


結果

誰かが Tpl を提案しましたが、これは素晴らしいライブラリですが、他の2つのノードをそれぞれ含むノードのツリーなど、任意のオブジェクトグラフは実行しないと思います。

もう1つの候補は、Enlightenmentウィンドウマネージャーのプロジェクトである Eet です。面白そうに見えますが、繰り返しになりますが、ネストされた構造をシリアル化する機能はないようです。

42
Daniel Lucraft

チェックアウト tpl 。概要から:

Tplは、Cデータをシリアル化するためのライブラリです。データは自然なバイナリ形式で保存されます。 APIは小さく、「邪魔にならない」ようにしようとします。 XMLを使用する場合と比較して、tplはCプログラムでより速く簡単に使用できます。 Tplは、構造体を含む多くのCデータ型をシリアル化できます。

16
Robert Gamble

私はあなたが図書館を求めていることを知っています。見つからない場合(:: boggle ::、これは解決された問題だと思います!)、解決策の概要を次に示します。

(実行時の)前処理なしでツリー/グラフをかなり単純にシリアル化するコードジェネレーター[1]を作成できるはずです。

ノード構造(typedef処理?)を解析し、含まれているデータ値を単純な方法で書き込む必要がありますが、ポインタの扱いには注意が必要です。

  • knowが単独で参照されている他のオブジェクト(char *name;)へのポインターの場合、ターゲットデータを直接シリアル化できます。

  • 多重参照される可能性のあるオブジェクトや、ツリーの他のノードの場合は、ポインター構造を表す必要があります。各オブジェクトにはシリアル化番号が割り当てられます。シリアル化番号は、ポインターの代わりに書き込まれます。現在のメモリ位置とシリアル番号の間の変換構造を維持します。ポインターが見つかったら、すでに番号が割り当てられているかどうかを確認します。割り当てられていない場合は、番号を割り当て、そのオブジェクトをシリアル化のためにキューに入れます。

また、読み返すにはノード番号/メモリ位置の変換ステップが必要であり、2つのパスで行う方が簡単な場合があります。各ノードが取得する場所を見つけるために、ポインタースロット(不良ポインター、警告)のノード番号でノードを再生成します。ポインタを固定してから、構造を再度ウォークします。

Tplについては何も知りませんが、便乗できるかもしれません。


オンディスク/ネットワーク形式は、おそらくいくつかのタイプ情報でフレーム化される必要があります。名前をマングリングするスキームが必要です。


[1] [〜#〜] root [〜#〜] このメカニズムを使用して、C++で非常に柔軟なシリアル化サポートを提供します。


遅い追加:これは、私が上記に示唆したように必ずしも簡単ではないことに気づきます。次の(不自然で不適切に設計された)宣言を検討してください。

enum {
   mask_none = 0x00,
   mask_something = 0x01,
   mask_another = 0x02,
   /* ... */
   mask_all = 0xff
};
typedef struct mask_map {
   int mask_val;
   char *mask_name;
} mask_map_t;
mask_map_t mask_list[] = {
   {mask_something, "mask_something"},
   {mask_another, "mask_another"},
   /* ... */
};
struct saved_setup {
   char* name;
   /* various configuration data */
   char* mask_name;
   /* ... */
};

struct saved_setupmask_nameを指すように、mask_list[foo].mask_nameアイテムを初期化するとします。

データをシリアル化する場合、struct saved_setup.mask_nameをどのように処理しますか?

データ構造の設計に注意するか、シリアル化プロセスにケース固有の情報を提供する必要があります。

これが私の解決策です。これは、malloc、free、mmap、munmapシステムコールの独自の実装を使用しています。与えられたサンプルコードに従ってください。参照: http://amscata.blogspot.com/2013/02/serialize-your-memory.html

私のアプローチでは、char配列を自分のRAM spaceとして作成します。次に、メモリを割り当てて解放するための関数があります。データ構造を作成した後、mmapを使用してchar配列をファイルに書き込みます。

それをメモリにロードしたいときはいつでも、munmapを使用してデータ構造を再びchar配列に配置する関数があります。ポインタ用の仮想アドレスがあるため、データ構造を再利用できます。つまり、データ構造を作成、保存、読み込み、再度編集して、再度保存できます。

6
Amith Chinthaka

eet をご覧ください。 Cデータ型(ネストされた構造を含む)を格納するためのEnlightenmentプロジェクトのライブラリ。 Enlightenmentプロジェクトのほぼすべてのライブラリはプレアルファ版ですが、eetはすでにリリースされています。ただし、循環参照を処理できるかどうかはわかりません。おそらく違います。

4
quinmars
3
plan9assembler

gwlibをチェックアウトする必要があります。シリアライザ/デシリアライザは広範囲にわたります。調べるために利用可能な広範なテストがあります。 http://gwlib.com/

3
gngrwzrd

私はあなたがグラフ構造を保存することについて話していると仮定していますが、そうでない場合は無視してください...

グラフを保存する場合、個人的には、グラフを隣接行列に変換する関数を実装することが最良のアイデアだと思います。次に、隣接行列をグラフデータ構造に変換する関数を作成できます。

これには3つの利点があります(アプリケーションで重要な場合と重要でない場合があります)。

  • 隣接行列は、グラフを作成して保存するための非常に自然な方法です
  • 隣接行列を作成してアプリケーションにインポートできます
  • 有意義な方法でデータを保存および読み取ることができます。

私はCSプロジェクトでこの方法を使用しましたが、間違いなく私は再びそれを行う方法です。

隣接マトリックスの詳細については、こちらをご覧ください。 http://en.wikipedia.org/wiki/Modified_adjacency_matrix

2
mmattax

別のオプションは Avro C で、これはCでの Apache Avro の実装です。

1

Binn ライブラリ(私の作成)を使用した例を次に示します。

  binn *obj;

  // create a new object
  obj = binn_object();

  // add values to it
  binn_object_set_int32(obj, "id", 123);
  binn_object_set_str(obj, "name", "Samsung Galaxy Charger");
  binn_object_set_double(obj, "price", 12.50);
  binn_object_set_blob(obj, "picture", picptr, piclen);

  // send over the network
  send(sock, binn_ptr(obj), binn_size(obj));

  // release the buffer
  binn_free(obj);

キーとして文字列を使用したくない場合は、整数をキーとして使用するbinn_mapを使用できます。

リストのサポートもあり、これらの構造はすべてネストできます。

  binn *list;

  // create a new list
  list = binn_list();

  // add values to it
  binn_list_add_int32(list, 123);
  binn_list_add_double(list, 2.50);

  // add the list to the object
  binn_object_set_list(obj, "items", list);

  // or add the object to the list
  binn_list_add_object(list, obj);
1
Bernardo Ramos

理論的にはYAMLはあなたがやりたいことをするべきです http://code.google.com/p/yaml-cpp/

うまくいくかどうか教えてください。

0
AndyL