データ構造をディスクにシリアル化して、後で再度読み込むことができるCライブラリが欲しいのですが。ネストされた構造を任意に受け入れる必要があり、循環参照が含まれる可能性があります。
このツールには、私のデータ構造を記述する構成ファイルが必要だと思います。ライブラリはコード生成の使用を許可されていますが、それなしでこれを実行することは可能だとかなり確信しています。
データの移植性には興味がありません。キャッシュとして使いたいので、環境が変わらなくても大丈夫です。
ありがとう。
結果
誰かが Tpl を提案しましたが、これは素晴らしいライブラリですが、他の2つのノードをそれぞれ含むノードのツリーなど、任意のオブジェクトグラフは実行しないと思います。
もう1つの候補は、Enlightenmentウィンドウマネージャーのプロジェクトである Eet です。面白そうに見えますが、繰り返しになりますが、ネストされた構造をシリアル化する機能はないようです。
チェックアウト tpl 。概要から:
Tplは、Cデータをシリアル化するためのライブラリです。データは自然なバイナリ形式で保存されます。 APIは小さく、「邪魔にならない」ようにしようとします。 XMLを使用する場合と比較して、tplはCプログラムでより速く簡単に使用できます。 Tplは、構造体を含む多くのCデータ型をシリアル化できます。
私はあなたが図書館を求めていることを知っています。見つからない場合(:: 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_setup
がmask_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配列に配置する関数があります。ポインタ用の仮想アドレスがあるため、データ構造を再利用できます。つまり、データ構造を作成、保存、読み込み、再度編集して、再度保存できます。
eet をご覧ください。 Cデータ型(ネストされた構造を含む)を格納するためのEnlightenmentプロジェクトのライブラリ。 Enlightenmentプロジェクトのほぼすべてのライブラリはプレアルファ版ですが、eetはすでにリリースされています。ただし、循環参照を処理できるかどうかはわかりません。おそらく違います。
gwlibをチェックアウトする必要があります。シリアライザ/デシリアライザは広範囲にわたります。調べるために利用可能な広範なテストがあります。 http://gwlib.com/
私はあなたがグラフ構造を保存することについて話していると仮定していますが、そうでない場合は無視してください...
グラフを保存する場合、個人的には、グラフを隣接行列に変換する関数を実装することが最良のアイデアだと思います。次に、隣接行列をグラフデータ構造に変換する関数を作成できます。
これには3つの利点があります(アプリケーションで重要な場合と重要でない場合があります)。
私はCSプロジェクトでこの方法を使用しましたが、間違いなく私は再びそれを行う方法です。
隣接マトリックスの詳細については、こちらをご覧ください。 http://en.wikipedia.org/wiki/Modified_adjacency_matrix
別のオプションは Avro C で、これはCでの Apache Avro の実装です。
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);
理論的にはYAMLはあなたがやりたいことをするべきです http://code.google.com/p/yaml-cpp/
うまくいくかどうか教えてください。