Delphi RTTI et C++Builder

De RAD Studio
Aller à : navigation, rechercher

Remonter à Utilisation des informations RTTI


Découverte du type à l'exécution (réflexion)

Désambiguïsation

Les informations RTTI de Delphi sont différentes des informations RTTI standard de C++ :

  • Les informations RTTI de Delphi vous permettent d'explorer les champs, les méthodes d'une classe, et ainsi de suite.
  • Les informations RTTI de C++ vous permettent d'identifier le type d'une variable et de comparer l'égalité des types, ou l'ordre de tri.

Remarque : L'option Projet > Options > Compilateur C++ > Activer RTTI du compilateur se réfère aux informations RTTI standard de C++.

Génération des informations RTTI

Seules les classes de style Delphi peuvent avoir des informations de style Delphi dans C++ (voir __declspec(delphiclass)).

Des informations RTTI peuvent être générées pour tout type de membre de classe (méthodes, champs, propriétés) avec toute visibilité (__published, public, protected, private). Pour contrôler la génération des informations RTTI, les spécifications suivantes peuvent être utilisées :

Exemple :

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

Sortie console :

wrHead: int @ 00

Dans cet exemple, les informations RTTI de classe sont extraites à l'aide de la fonction __delphirtti (qui renvoie un pointeur sur une variable TTypeInfo). Il est possible de faire la même chose avec l'opérateur __classid. Voir le code suivant

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

Remarque : Les informations RTTI extraites avec __delphirtti peuvent différer selon les plates-formes. Par exemple, sur iOS et macOS, la fonction __delphirtti d'un caractère char16_t renvoie une variable PTypeInfo qui correspond aux informations RTTI de Delphi pour le type WideChar de Delphi.

Sur la plate-forme Windows, la fonction __delphirtti d'un caractère wchar_t renvoie une variable PTypeInfo qui correspond aux informations RTTI de Delphi pour le type WideChar de Delphi.

Cette fonctionnalité est illustrée dans l'exemple de code suivant :

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

Sortie :

Plate-forme Sortie

WIN64

Kind=1, Name='char16_t'

Kind=9, Name='Char'

iOS

Kind=9, Name='Char'

Kind=9, Name='wchar_t'

Enracinement du type

Vous ne pouvez pas utiliser les méthodes FindType et GetTypes pour obtenir les informations RTTI de Delphi pour des classes définies en langage C++. La raison est que FindType et GetTypes effectuent des recherches dans les packages d'exécution, et que le lieur C++ n'effectue aucun enracinement de type.

D'autre part, le lieur Delphi enracine les informations RTTI dans les tables d'information de packages. Cela signifie, qu'en C++, vous pouvez parcourir les informations RTTI pour les unités trouvées dans les modules Delphi (packages), comme dans le code suivant

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

Remarque : Sur la plate-forme iOS, la liaison est effectuée de façon statique, donc aucune information RTTI n'est enracinée. Cependant, vous pouvez obtenir les informations RTTI si vous utilisez la méthode GetType, comme illustré dans l'exemple de code suivant :

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

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

Attributs

Les attributs Delphi ne sont pas pris en charge dans C++Builder. C++Builder prend en charge les attributs C++11, qui sont différents des attributs Delphi :

  • Les attributs Delphi représentent des informations supplémentaires pour le programmeur et ils peuvent être extraits à l'exécution.
  • Les attributs C++11 représentent des informations supplémentaires pour le compilateur et ne sont pas spécifiques à RTTI.

Voir aussi

Informations RTTI de Delphi

Informations RTTI de Delphi dans C++Builder

Informations RTTI de C++