Migration du code C++ en mobile depuis le bureau

De RAD Studio
Aller à : navigation, rechercher

Remonter à Considérations C++ pour les applications multi-périphériques


Cette rubrique explique comment migrer un code C++ existant écrit pour les plates-formes de bureau afin qu'il fonctionne sur les plates-formes mobiles.

Le langage Delphi a subi des modifications pour les plates-formes mobiles. Un grand nombre de ces modifications affectent le portage du code C++ depuis les plates-formes de bureau vers les plates-formes mobiles, comme décrit dans cette rubrique.

Particularités du code mobile C++

Vous devez prendre en compte certaines particularités ou erreurs éventuelles lors du développement de vos applications C++ pour les plates-formes mobiles ou de la migration du code de bureau C++ en code mobile.

A propos des types chaîne

Les compilateurs mobiles de Delphi ont éliminé tous les types de chaînes (tels que AnsiString, UTF8String, RawByteString, WideString, ShortString, PAnsiChar, etc.) à l'exception de System.String, qui est mappé en type System::UnicodeString C++. C++ Mobile fournit toujours AnsiString, UTF8String, RawByteString et ShortString. Mais l'API de ces types est un sous-ensemble de celle fournie dans les versions C++ de ces types pour les plates-formes de bureau.

Les méthodes suivantes de la classe System.AnsiStringT ne sont pas disponibles dans С++ Mobile :

Méthodes de System.AnsiStringT
(AnsiString, UTF8String, RawByteString)
qui ne sont pas disponibles dans les plates-formes mobiles
bool IsPathDelimiter(int index) const
int LastDelimiter(const AnsiStringBase& delimiters) const
TStringMbcsByteType ByteType(int index) const
bool IsLeadByte(int index) const
bool IsTrailByte(int index) const
char* AnsiLastChar() const
static AnsiStringT LoadStr(HINSTANCE hInstance, int ident)
int WideCharBufSize(int codePage) const
wchar_t* WideChar(wchar_t* dest, int destSize, int codePage) const
AnsiStringT& LoadStringW(HINSTANCE hInstance, int ident)

Comme nous l'avons mentionné ci-dessus, les compilateurs mobiles Delphi ont éliminé PAnsiChar (en C++, cela correspond à char*) et ShortString. Cette modification n'est souvent pas évidente et peut produire des résultats inattendus. A des fins de clarification, considérons les exemples suivants :

PAnsiChar: TStringBuilder.Append

Comme Delphi mobile ne supporte pas PAnsiChar, les méthodes de la classe TStringBuilder qui acceptent les arguments du type PAnsiChar ont été retirées :

TStringBuilder* __fastcall Append(const char * Value)/* overload */;
TStringBuilder* __fastcall Append(const System::RawByteString Value)/* overload */;

Dans ce cas, le code C++ qui est similaire à l'extrait de code suivant ne fonctionnera plus comme prévu :

std::auto_ptr<TStringBuilder> sb(new TStringBuilder());
// ...
sb->Append("Hello");

Dans l'exemple ci-dessus, C++ mobile invoque en mode silencieux la méthode Append qui attend un paramètre bool. Pour fonctionner sur des plates-formes de bureau et mobiles, ce code doit être écrit de la façon suivante :

std::auto_ptr<TStringBuilder> sb(new TStringBuilder());
// ...
sb->Append(String("Hello"));

ShortString: TTypeInfo.Name

ShortString n'est pas supporté dans Delphi mobile. Par conséquent, toutes les déclarations qui utilisaient ShortString sur les plates-formes de bureau, comme TTypeInfo, ont également changé. Le membre Name est un octet simple sur Mobile. En d'autres termes, le code C++ suivant échoue dans les plates-formes mobiles :

static System::UTF8String getTypeInfoName(System::Typinfo::PTypeInfo ti)
{
  return System::UTF8String(ti->Name);
}

Sur Mobile, la fonction ci-dessus renvoie en mode silencieux une chaîne avec une valeur de type Byte, pas le nom du type. Pour fonctionner sur des plates-formes de bureau et mobiles, le code doit être écrit de la façon suivante :

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
}

A propos du transtypage

C++ mobile ne supporte pas le transtypage de type C pour les pointeurs en classes de style Delphi, telles que TButton ou TSpeedButton.

Par exemple, l'extrait de code suivant est incorrect :

void Callback(void* p)
{
   ((TButton*)p)->Enable = true;
}

A la place, vous devez utiliser l'opérateur reinterpret_cast, qui convertit tout type de pointeur en un autre type de pointeur, même de classes non associées. Pour utiliser l'extrait de code C++ ci-dessus pour les plates-formes mobiles, modifiez-le comme suit :

void Callback(void* p)
{
    reinterpret_cast<TButton*>(p)->Enable = true;
}

A propos des fonctionnalités C++11

Les compilateurs C++ pour iOS (BCCIOSARM et BCCIOSARM64) utilisent la bibliothèque STL incluse avec le SDK iOS (pas la bibliothèque C++ standard Dinkumware, qui est prise en charge par les applications C++ sur les plates-formes de bureau).

Les compilateurs C++ pour iOS prennent seulement en charge les fonctionnalités principales de C++11 qui sont implémentées par le compilateur BCC64. Les compilateurs iOS ne prennent pas en charge les fonctionnalités de bibliothèque C++11 standard, qui sont disponibles pour nos autres compilateurs C++ (dans la bibliothèque standard Win64, dans les bibliothèques Boost et dans les en-têtes C++11, comme regex, chrono, etc.).

Pour de plus amples informations à propos des en-têtes spécifiques à C++11, voir :

Utilisation des alias forts C++

Les versions antérieures de Delphi mappaient les types intégrés tels que NativeInt, NativeUInt et WordBool en types intégrés C++. Les versions les plus récentes de Delphi gèrent ces types comme des alias forts, comme TAlphaColor ou TImageIndex. Pour être compatible avec ce changement, C++ crée aussi des alias forts en utilisant un wrapper de classe.

Par exemple, pour gérer un NativeInt, vous devez spécifier explicitement le type (NativeInt). A des fins de clarification, considérons les cas suivants :

NativeInt i = 10; // error
NativeInt i = NativeInt(10);  // OK

Utilisation de l'opérateur delete

Supposons que votre code contient l'opérateur delete :

delete ptr

ptr est un pointeur sur le bloc mémoire à libérer.

Dans les plates-formes mobiles, l'opérateur delete n'appelle pas toujours un destructeur d'objet. L'opérateur delete fonctionne comme suit :

  • Si ptr pointe sur une classe de style Delphi, l'opérateur delete décrémente simplement le compteur RefCount (le nombre de références à cette instance de classe). Le destructeur d'objet est invoqué seulement en l'absence d'autres références à cet objet.
  • Si ptr pointe sur une classe de style non Delphi, l'opérateur delete fonctionne exactement comme dans une application C++ pour les plates-formes de bureau.

Résolution des avertissements du lieur à propos des littéraux chaîne

L'erreur suivante du lieur :

 Error: "__ZN6SystemplEPKwRKNS_13UnicodeStringE", referenced from ...

indique que votre code contient un littéral constante wchar_t ajouté (via l'opérateur +) à un UnicodeString.

La solution consiste à changer le littéral constante en un char16_t. Nous vous recommandons d'utiliser la macro _D(<lit-string>) pour les littéraux chaîne interagissant avec UnicodeSTring.

Par exemple, remplacez :

 L"Hello " + System::String("world!")

par

_D("Hello ") + System::String("world!")

Pour plus d'informations sur les plates-formes mobiles, voir Littéraux chaîne char16_t et wchar_t sur la plate-forme OS X.

Définitions requises pour les plates-formes mobiles

Pour que votre projet puisse se compiler pour les plates-formes mobiles, ainsi que pour les plates-formes de bureau, vous devez préfixer votre implémentation de projet et vos fichiers d'en-tête précompilés (par exemple, "Project.cpp" et "ProjectPHC.h") avec l'extrait de code #ifdef suivant :

#ifdef _WIN32
  #include <tchar.h>
#else
  typedef char _TCHAR;
  #define _tmain main
#endif

Eliminer les composants FireMonkey qui ne sont pas supportés sur C++ Mobile

Composant utilisé dans les

plates-formes de bureau

Composant(s) à utiliser dans les
plates-formes mobiles
TMainMenu, TPopupMenu TToolBar, TSpeedButton, TPopup


Vous trouverez ci-dessous des détails relatifs au remplacement de ces types non supportés.

TMainMenu ou TPopupMenu

Ces composants ne sont pas supportés dans les plates-formes mobiles. Pour migrer votre code de bureau C++ en code mobile, vous devez retirer TMainMenu ou TPopupMenu de votre code, et utiliser à la place les composants mobiles supportés suivants :

Pour créer un menu qui utilise TPopup

  1. Sélectionnez le composant TToolBar dans la palette d'outils, et déposez-le sur le Concepteur de fiches.
  2. Sélectionnez le composant TSpeedButton dans la palette d'outils et déposez-le sur le ToolBar.
  3. Sélectionnez le composant SpeedButton sur le Concepteur de fiches, puis sélectionnez buttonstylelabel dans la propriété StyleLookup de l'inspecteur d'objets.
  4. Sélectionnez le composant TPopup dans la Palette d'outils, et déposez-le sur le Concepteur de fiches.
  5. Dans la vue Structure, transformez ce TPopup en enfant du TSpeedButton.
  6. Sélectionnez le composant TLabel dans la Palette d'outils, et déposez-le sur le Concepteur de fiches.
  7. Dans la vue Structure, transformez ce TLabel en enfant du TPopup.
  8. Sélectionnez le TLabel et définissez dans l'inspecteur d'objets la propriété HitTest sur True.

Remarque : Pour ajouter plusieurs libellés, répétez les étapes 6 à 8.

StructureView.png
  1. Dans l'éditeur de code, pour le composant TSpeedButton, implémentez le gestionnaire d'événement onClick suivant :
    void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
    {
         // Open the pop-up window.
         Popup1->IsOpen = True;
    }
    
  2. Pour chaque composant TLabel ajouté au TPopup, implémentez les gestionnaires d'événement onClick appropriés.


Voir aussi