Delphi RTTI と C++Builder

提供: RAD Studio
移動先: 案内検索

RTTI の操作 への移動


実行時型検索(リフレクション)

あいまい性の解消

Delphi RTTI は、標準の C++ RTTI とは以下の点が異なります。

  • Delphi RTTI では、クラスのフィールドやメソッドなどを調べることができます。
  • C++ RTTI では、変数の型を特定したり、型を比較して等しいかどうかや照合順序を確認することができます。
メモ: コンパイラ オプション[プロジェクト|オプション...|C++ コンパイラ|RTTI を有効にする]は、標準の C++ RTTI を指しています。

RTTI の生成

C++ で Delphi 形式の RTTI を持つことができるのは Delphi 形式のクラスだけです(「__declspec(delphiclass)」を参照)。

RTTI は、どのような可視性(__published、public、protected、private)のどのような種類のクラス メンバ(メソッド、フィールド、プロパティ)に対しても生成することができます。 RTTI の生成を制御するには、以下の指定を使用できます。

例:

#include <System.hpp>
#include <Rtti.hpp>
#include <tchar.h>
#include <stdio.h>

// Enable RTTI generation for private fields
#pragma explicit_rtti fields(private)

class __declspec(delphiclass) TBuffer {
private:
	int wrHead, rdHead;

	// ...
public:
	TBuffer() {

	}
};

// ---------------------------------------------------------------------------

int _tmain(int argc, _TCHAR* argv[]) {
	TRttiContext context;

	// Get class RTTI
	TRttiInstanceType *cls = dynamic_cast<TRttiInstanceType*>
		(context.GetType(__delphirtti(TBuffer)));

	if (cls) {
		// Get field RTTI
		TRttiField *field = cls->GetField("wrHead");
		if (field) {
			printf("%ls", field->ToString().c_str());
		}
		else {
			puts("\"wrHead\" doesn't have RTTI");
		}
	}
	else {
		puts("\"TBuffer\" doesn't have RTTI");
	}

	return 0;
}

コンソール出力:

wrHead: int @ 00

この例では、__delphirtti 関数(TTypeInfo 変数のポインタを返す)を使ってクラス RTTI を取り出しています。 同じことを __classid 演算子を使って行うこともできます。 以下のコードを参照してください。

	TRttiInstanceType *cls = dynamic_cast<TRttiInstanceType*>
		(context.GetType(__classid(TBuffer)));

Windows プラットフォームでは、wchar_t__delphirtti は、Delphi WideChar の Delphi の RTTI に一致する PTypeInfo を返します。

この機能を以下のコード例で示します。

#include <stdio.h>

static System::UTF8String getTypeInfoName(System::Typinfo::PTypeInfo ti)
{
#ifndef _DELPHI_NEXTGEN
  return System::UTF8String(ti->Name);
#else
  int len = ti->Name;
  const char* p = reinterpret_cast<char*>(&(ti->Name));
  return System::UTF8String(p+1, len);
#endif
}

 int main()
{
  System::Typinfo::PTypeInfo pti;
  pti = __delphirtti(char16_t);
  printf("Kind=%d, Name='%s'\n", pti->Kind, getTypeInfoName(pti).c_str());
  pti = __delphirtti(wchar_t);
  printf("Kind=%d, Name='%s'\n", pti->Kind, getTypeInfoName(pti).c_str());
  return 0;
}

出力:

プラットフォーム 出力

WIN64

Kind=1, Name='char16_t' Kind=9, Name='Char'

型情報の格納

FindType および GetTypes メソッドを使用して、C++ 言語で定義されたクラスの Delphi RTTI を取得することはできません。これは、FindType および GetTypes は、実行時パッケージ内で検索を実行しますが、C++ パッケージでは型ルーティングを行わないためです。つまり、C++Builder によって構築された動的パッケージについての情報の取得に、TRttiPackage は使用できないということになります。

一方、Delphi リンカは、パッケージ情報テーブルで RTTI のルーティングを行います。つまり、C++ では、Delphi スタイル RTTI を Delphi モジュール(パッケージ)からロードおよび使用できることとなります。次にコードを示します:

TRttiContext context;
TRttiType *rttiType = context.FindType("Classes.TStringList");
printf("%ls", rttiType->ToString()); // displays TStringList

属性

Delphi 属性は、C++Builder ではサポートされていません。C++Builder は、Delphi 属性とは異なる C++11 属性 をサポートしています:

  • Delphi 属性はプログラマに追加情報を提供するもので、実行時に抽出可能です。
  • C++11 属性はコンパイラに追加情報を提供するもので、RTTI に特有のものではありません。

関連項目

Delphi RTTI

C++Builder における Delphi RTTI

C++ の RTTI