Migration du code C++ en mobile depuis le bureau
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.
Sommaire
- 1 Particularités du code mobile C++
- 2 Définitions requises pour les plates-formes mobiles
- 3 Eliminer les composants FireMonkey qui ne sont pas supportés sur C++ Mobile
- 4 Voir aussi
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 :
- C++11
- C Standard Library header files (les en-têtes spécifiques à C++11 sont repérés par "(since C11)")
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
où 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érateurdelete
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érateurdelete
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
- Sélectionnez le composant TToolBar dans la palette d'outils, et déposez-le sur le Concepteur de fiches.
- Sélectionnez le composant TSpeedButton dans la palette d'outils et déposez-le sur le ToolBar.
- Sélectionnez le composant SpeedButton sur le Concepteur de fiches, puis sélectionnez buttonstylelabel dans la propriété StyleLookup de l'inspecteur d'objets.
-
- Pour de plus amples détails sur la sélection d'un style dans les applications multi-périphériques, voir Tutoriel mobile : Utilisation d'un composant Bouton avec différents styles (iOS et Android).
-
- Sélectionnez le composant TPopup dans la Palette d'outils, et déposez-le sur le Concepteur de fiches.
- Dans la vue Structure, transformez ce TPopup en enfant du TSpeedButton.
- Sélectionnez le composant TLabel dans la Palette d'outils, et déposez-le sur le Concepteur de fiches.
- Dans la vue Structure, transformez ce TLabel en enfant du TPopup.
- 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.
-
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; }
- Pour chaque composant TLabel ajouté au TPopup, implémentez les gestionnaires d'événement onClick appropriés.