Delphi RTTI and C++Builder

From RAD Studio
Jump to: navigation, search

Go Up to Working with RTTI

Run-Time Type Discovery (Reflection)

Disambiguation

Delphi RTTI is different and separate from standard C++ RTTI:

  • Delphi RTTI allows you to explore the fields, methods, and so forth, of a class.
  • C++ RTTI allows you to identify the type of a variable and compare types for equality or collating order.
Note: The compiler option Project > Options > C++ Compiler > Enable RTTI refers to standard C++ RTTI.

RTTI Generation

Only Delphi-style classes can have Delphi-style RTTI in C++ (see __declspec(delphiclass)).

RTTI can be generated for any kind of class member (methods, fields, properties) with any visibility (__published, public, protected, private). To control the RTTI generation, the following specifications can be used:

Example:

#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;
}

Console output:

wrHead: int @ 00

In this example, the class RTTI is extracted with the help of the __delphirtti function (which returns a pointer to a TTypeInfo variable). It is possible to do the same thing with the __classid operator. See the following code:

	TRttiInstanceType *cls = dynamic_cast<TRttiInstanceType*>
		(context.GetType(__classid(TBuffer)));
Note: RTTI information extracted with __delphirtti might differ between platforms. For example, on iOS and OSX, the __delphirtti of a char16_t returns a PTypeInfo that matches Delphi's RTTI for the Delphi WideChar.

On the Windows platform, the __delphirtti of a wchar_t returns a PTypeInfo that matches Delphi's RTTI for the Delphi WideChar.

The functionality is shown in the following code example:

#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;
}

Output:

Platform Output

WIN64

Kind=1, Name='char16_t'

Kind=9, Name='Char'

iOS

Kind=9, Name='Char'

Kind=9, Name='wchar_t'

Type Rooting

You cannot use the FindType and GetTypes methods to get Delphi RTTI for classes defined in C++ language. This is because FindType and GetTypes perform searches in the run-time packages, but the C++ linker does no type rooting.

On the other hand, the Delphi linker roots the RTTI in package information tables. This means that in C++ you can browse the RTTI for units found in Delphi modules (packages), as in the following code:

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

Note: On the iOS platform, linking is done statically, and therefore no RTTI is rooted. However, you can obtain the RTTI if you use the GetType method, as shown in the following code example:

  TRttiContext context;
  TRttiType *rttiType = context.GetType(__delphirtti(Fmx::Layouts::TLayout));

  if (rttiType == NULL) {
     ShowMessage("RTTI not generated");
  }  else {
    ShowMessage(rttiType->ToString());
  }

Attributes

Delphi attributes are not supported in C++Builder. C++Builder supports C++11 attributes, which are different from Delphi attributes:

  • Delphi attributes represent additional information for the programmer and can be extracted at run time.
  • C++11 attributes represent additional information for the compiler and are not specific to RTTI.

See Also

Delphi RTTI

Delphi RTTI in C++Builder

C++ RTTI