Theolizer  Version.1.1.3
serializer for C++ / Do you want to update your classes easily ?
概要


1.Theolizerとは


TheolizerはC++11で記述されたC++用のシリアライザです。
Theolizerを使うことで次のようなプログラムの開発が容易になります。

  • クラスや構造体等とその組合せで作れられた複雑なデータ構造を
  • 「ファイルへ保存/回復」するプログラム
  • 「通信回線で送受信」するプログラム

また、C++をベターCとしてお使いの方にも使って頂けるよう設計しておりますのでお気軽にお試し下さい。


2.対応環境


マルチ・プラットフォームでC++11規格コンパイラに対応できるよう設計しています。
現時点でテストできている環境は下記の通りです。

2-1.v1.1.3以降

OSC++コンパイラ
Windows 10 Professional 64bitVisual Studio C++ 2017 Community Version 15.2
MinGW 7.1.0 32bit posix dwarf(mingw-w64-install.exe)
MinGW 7.1.0 64bit posix seh(mingw-w64-install.exe)
ubuntu 16.04 LTS 64bitgcc 5.4.0(Ubuntu 5.4.0-6ubuntu1~16.04.2)

将来的にOS X + apple-llvmに対応する準備を進めています。

次に、ユーザ・プログラムをビルドする際に関連するツールは以下の通りです。

その他のツールバージョン備考
CMake3.8.0以上ユーザ・プログラムのビルドをアシストする際に用います
Theolizerのビルドに使用しています
boost1.64.0以上Theolizerの内部で使用しています

CMakeは必須ではありませんが、使用することを強く推奨します。
あなたのプログラムでBoostを使っている場合、それがTheolizerで使っているものと異なるバージョンの時、注意が必要になります。「1.Theolizerライブラリの選択 」を参照下さい。

なお、CMakeはバージョンによって認識可能なBoostのバージョンが異なります。調べた範囲では以下でした。Linuxではお使いになるBoostのバージョンに合わせて選択下さい。(WindowsではCMake 3.8.0以降のVisual Studio対応機能を用いますのでCMake 3.8.0以降のみ使用可能です。)

CMakeバージョンBoostバージョン
3.8.01.64.0以下
3.7.21.63.0以下
3.7.11.62.0以下
3.6.01.61.0以下
3.5.11.61.0以下
3.5.01.61.0以下

2-2.v1.1.2以前

OSC++コンパイラ
Windows 10 Professional 64bitVisual Studio C++ 2015 Community update 3
MinGW 5.4.0 32bit posix dwarf
MinGW 5.4.0 64bit posix seh
ubuntu 16.04 LTS 64bitgcc 5.4.0(Ubuntu 5.4.0-6ubuntu1~16.04.2)


次に、ユーザ・プログラムをビルドする際に関連するツールは以下の通りです。

その他のツールバージョン備考
CMakeVisual C++は3.8.0以上
その他は3.5.0以上
ユーザ・プログラムのビルドをアシストする際に用います
Theolizerのビルドに使用しています
boost1.59.0以上Theolizerの内部で使用しています


3.Theolizerの特長


3-1.自動シリアライズ

C++は、クラスや構造体(以下、まとめてクラスと呼びます)に含まれるメンバのリストをプログラムがアクセスすることはできません。(メンバ1つ1つを名前を指定してアクセスすることはできますが、forループ等でメンバを次々と列挙することができないのです。) ですので、クラスをシリアライズするためにはメンバのリストを、クラス定義とは別に改めて作成する必要がありました。
TheolizerはClang/LLVMに含まれるlibToolinglibToolingの構文解析機能を用いてクラス定義を解析し、メンバのリストを自動生成します。
従って、クラス定義を変更した時もメンバ・リストへの反映漏れが無く、プログラム開発が捗ります。

3-2.保存先指定

1つのクラスに属するメンバ変数を保存する時、複数の異なるファイルへ保存したい時もあると思います。一部のメンバ変数は設定ファイルへ保存し、また別のメンバはデータ・ファイルへ保存したいというケースは少なくないと思います。また、一部のメンバ変数(ファイル・ハンドル等)は保存しないことも多いでしょう。

Theolizerはメンバ変数に保存先や保存の有無を指定することでクラスを分割して異なるファイルへ保存したり、一部を通信で他のプログラムへ送信したりすることができます。

3-3.オブジェクト追跡

一般にポインタをファイルへ保存し、プログラムを再起動した後でそのポインタを回復しても意味はありません。ポイント先のメモリ・アドレスはプログラムの再起動前後で異なることが一般的だからです。

Theolizerはポイント先のデータも一緒にファイルへ保存するのであればオブジェクト追跡によりポインタを有意味に回復することができます。もちろん通信時も同様です。
また、ポイント先がクラスの場合、その各メンバに保存先指定することができますので全てを保存する必要はありません。
これにより複雑なデータ構造を容易に保存/回復・送受信できます。
オブジェクト追跡機能はboost::serializationを参考に開発しました。

3-4.プログラム変更対応

シリアライザを使って保存するということは、内部データの構造を保ったままファイルへ保存するということです。内部データ構造はプログラムの変更に伴い変更されるため、旧プログラムで保存されたファイルを回復できるようにするためには内部データ構造の変更に強い制限がかかります。

Theolizerはその制限を大幅に緩和し、古いプログラムで保存したデータを新しいプログラムで回復できます。
更に、新しいプログラムで古いプログラムが読めるデータを保存するプログラムを開発することも可能です。

クラス(class/struct)とenum型の定義を変更するに際して、2種類の変更対応方法を用意しています。

  1. アップデート
    バージョン番号を変更しない方法です。
  2. バージョン・アップ
    クラスやenum型に割り当てた(ローカル)バージョン番号を1つ上げて対応する方法です。

それぞれ特徴があります。

方式特徴
アップデート1.変更が容易です。
2.自動生成するソース・コードが増えないためコンパイラへの負荷が軽いです。
3.古いデータを新しいプログラムで回復できますが、逆はサポートしていません。
バージョン・アップ1.より大幅な変更に対応できます。
2.旧バージョン形式のデータを保存することができます。
3.変更作業は少し手間がかかります。
4.旧バージョンの変数リストやシンボル・リストを保持するため、
バージョン番号を上げる度に自動生成されるソース・コードが増えます。

可能な時はアップデートにて変更対応し、それでは不足の場合にバージョン・アップすることがお薦めです。

まとめると次のような特長があります。

  1. クラス定義、enum定義の変更(アップデート/バージョンアップ)
    • クラスのメンバ変数の追加/削除/順序変更に対応しています。
    • enum型のシンボルの追加/削除/定義順序変更に対応しています。
      また、シンボル名で保存/回復する時はシンボル値を、シンボル値保存の時はシンボル名を自由に変更できます。

  2. クラスについてバージョン・アップ/ダウン処理を記述できます
    • クラスをバージョン・アップする際に行いたい処理を記述できます。
      例えば、変数にオフセットを追加した時、そのオフセットを加える処理などです。
    • バージョン・ダウン処理を定義できます。
      例えば、オフセットを引く処理などです。
    • クラスは名前対応と順序対応を、enum型はシンボル名保存とシンボル値保存を切り替えることができます。
      開発当初は名前対応/シンボル名保存にて変更しやすくしておき、安定したら順序対応/シンボル値保存として効率アップすることが可能です。更に元へ戻すこともできます。

  3. バージョン・アップ/ダウンをカスケードに処理します
    例えば、Ver.4をVer.5へバージョンアップした時、従来はVer.4→Ver.5のプログラム開発だけでなく、Ver.1~Ver.3→Ver.4のプログラムをVer.1~Ver.3→Ver.5へ改造する必要がありました。Theolizerはバージョン・アップ/ダウン処理をカスケード(Ver.1→Ver.2→Ver.3→Ver.4→Ver.5)に行いますので、Ver.4→Ver.5のプログラムを開発するだけで済みます。
    これによりバージョンが上がった時のプログラム開発を大きく低減できます。(注)

  4. 旧バージョン形式のデータを保存することができます
    保存したい形式のバージョン番号を指定することで、新しいバージョンのプログラムが古いバージョンのプログラムが保存する形式でデータ保存可能です。
    なお、指定された古いバージョンに複数のアップデートが含まれる場合は最後のアップデート版が保存されます。
(注)バージョン・アップ/ダウンにおける不可逆性に注意
Theolizerのバージョン・ダウン機能は旧プログラムで回復可能なデータを保存することを目的としています。

バージョン・アップする時はenum値や変数の追加を行うケースが多いですが、古い形式のデータを保存する時には、その追加されたデータを削除します。(古いバージョンのプログラムはその追加されたデータの存在を知らないため、もしも残すと古いプログラムが処理できなくなるためです。) なので、新バージョン・プログラムが保存した旧バージョン・データを、再度新バージョン・プロクラムで回復した時、元のデータに戻ることを本質的に期待できません。


4.Theolizerの仕組み


 Theolizerはドライバとライブラリの2つで構成されています。

項目 内容
ドライバあなたのソースを解析して、シリアライズ処理に必要なコードを自動生成します。
ライブラリあなたのプログラムとリンクして、シリライズ処理を行います。

4-1.ドライバ

Theolizerドライバはあなたのビルド・プロジェクト(makeやVisual Studio)とコンパイラの間に割り込み、下記を自動的に行います。

  1. ビルド・プロジェクトの指示に従ってあなたのソース・コードを解析します。
  2. シリアライズ/デシリアライズ処理を行うために必要なソース・コード(主にクラス・メンバのリスト)を自動生成します。
    C++ソース・コードの解析には、Clang/LLVMに含まれるlibToolingを用いて構文解析を行っています。
  3. 通常のコンパイラとリンカがあなたのプログラムと自動生成されたソース・コードをビルドし、Theolizerライブラリをリンクします。
自動生成するソースのファイル名
自動生成するソース・ファイル名は、コンパイルするソースファイル名.theolizer.hppです。 例えば、main.cppの場合、main.cpp.theolizer.hppとなります。

4-2.ライブラリ

Theolizerライブラリはあなたのプログラムとリンクして、データ構造のシリアライズとデシリアライズを行います。

4-3.Theolizerドライバが割り込む仕組み

ビルド・プロジェクトとコンパイラの間にTheolizerドライバを割り込む仕組みのポイントは次の3点です。

  1. ビルド・システムにTheolizerドライバをコンパイラとして起動させる
  2. Theolizerドライバにソース自動生成が必要であることを伝達し、自動生成処理する
  3. Theolizerドライバに元コンパイラのパスを伝達し、元のコンパイラへ処理を引き継ぐ

4-3-1. Theolizerドライバをコンパイラとして起動させる

4-3-1-1.Visual Studioの場合

  • Theolizerインストール時に準備
    Theolizerのインストール先フォルダにmsbuild-binフォルダを追加し、そこへTheolizerドライバをcl.exeとして保存します。
  • ビルド・プロジェクト生成

CMake 3.8.0にてVS_USER_PROPSと言うVC++のプロジェクトへインクルード指定を追加するプロパティが追加されました。
これを使ってターゲットのプロジェクト・ファイル(*.vcxproj)に<Import Project>キーを追加し、theolizer.propsをインクルードするようにしました。
そして、theolizer.propsにて、コンパイル時に使われるPATHを指定する<ExecutablePath>の先頭に上記msbuild-binフォルダを追加しました。

以上により、Theolizerを使用するプロジェクトにおいてTheolizerドライバがコンパイラとして起動します。

4-3-1-2.その他(gcc/mingw)の場合

対象のプロジェクトのCMAKE_CXX_COMPILERにTheolizerドライバのフルパスを設定しました。
これはmakefileのコンパイラに反映されますので、呼び出すコンパイラを変更できます。
(なお、Visual Studioはmakeではなくマイクロソフト独自のMSBuildでビルドするためこの方法が機能しません。)

4-3-2.Theolizerドライバにソース自動生成が必要であることを伝達する

CMakeでTHEOLIZER_DO_PROCESSマクロをコンパイラ・オプションで定義するようにしまた。 このマクロがオプションで指定された時、Theolizerドライバはソース自動生成処理を行います。 そうでない時は、Theolizer関連オプションを除く全ての引数で元コンパイラを起動(パススルー)します。

4-3-3.Theolizerドライバに元コンパイラのパスを伝達する

4-3-3-1.Visual Studioの場合

CMakeは*.rspファイルに全てのオプションを記述してコンパイラへ渡します。その為、Theolizerドライバでそのオプションを削除して元コンパイラへ引き継ぐことが難しいです。しかし、削除しないとcl.exeが「知らないオプション」として警告します。 そこで、マクロ定義(/Dtheolizer_original_compiler=<元コンパイラのパス>)で伝達することで警告表示されないようにしました。マクロ定義はリンカへ伝達する必要がないので伝わらないようです。

4-3-3-2.その他(gcc/mingw)の場合

CMakeはgcc/mingw用にはコンパイルとリンクを分解してg++を呼び出します。 リンクの時ldを直接呼ぶわけでなく、g++にリンク指定して呼び出します。 どちらの場合もTheolizerドライバが起動されることになります。 そして、リンク動作時は-Dオプションは渡ってきません。マクロ定義はコンパイラのみ必要なオプションだからだと思います。 しかし、その結果、リンク時に起動されたTheolizerドライバが元コンパイラのパスを得ることができず、元コンパイラをパススルー起動できません。

そこで、msvc以外の時は--theolizer_original_compiler=<元コンパイラのパス>オプションで元コンパイラのパスを伝達するようにしました。

4-3-4. 使い方の変更について

上記はfind_packageで用いるTHEOLIZERConfig.cmake内部で対応しました。ですので、ユーザ・プログラム用のCMakeLists.txtは従来のままで使用できます。従来必要であったコンパイラのリプレース操作が不要になります。

なお、Visual Studioをお使いの場合は、CMakeを3.8.0以上へアップデートする必要があります。