Migrieren von C++-Code zu mobilen Anwendungen vom Desktop aus
Nach oben zu Gesichtspunkte für geräteübergreifende C++-Anwendungen
In diesem Thema wird beschrieben, wie Sie vorhandenen C++-Code, der für Desktop-Plattformen geschrieben wurde, migrieren, sodass er auf mobilen Plattformen verwendet werden kann.
Für mobile Plattformen wurden einige Änderungen an der Delphi-Sprache vorgenommen. Viele dieser Änderungen wirken sich auf die Portierung von C++-Code von Desktop-Plattformen zu mobilen Plattformen aus, wie in diesem Thema beschrieben.
Inhaltsverzeichnis
Besonderheiten von mobilem C++-Code
Es gibt einige Besonderheiten oder häufige Fehler ("Gotchas"), die Sie beim Entwickeln von C++-Anwendungen für mobile Plattformen oder beim Migrieren von C++-Desktop-Code zu mobilem Code berücksichtigen sollten.
Allgemeines zu String-Typen
Aus den mobilen Delphi-Compilern wurden alle String-Typen (wie AnsiString, UTF8String, RawByteString, WideString, ShortString, PAnsiChar usw.) entfernt, mit Ausnahme von System.String, der dem C++-Typ System::UnicodeString zugeordnet ist. C++ für mobile Anwendungen enthält weiterhin die Typen AnsiString, UTF8String, RawByteString und ShortString. Aber die API dieser Typen umfasst nur eine Teilmenge der C++-Versionen dieser Typen für Desktop-Plattformen.
Die folgenden Methoden der Klasse System.AnsiStringT stehen in C++ für mobile Anwendungen nicht zur Verfügung:
Methoden von System.AnsiStringT (AnsiString, UTF8String, RawByteString), die nicht für mobile Plattformen verfügbar sind |
---|
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)
|
Wie oben bereits erwähnt, wurden PAnsiChar
(einspricht in C++ char*
) und ShortString
aus den mobilen Delphi-Compilern entfernt. Diese Änderung ist oft nicht klar und kann zu unerwarteten Ergebnissen führen. Sehen Sie sich zur Klärung die folgenden Beispiele an:
PAnsiChar: TStringBuilder.Append
Da Delphi für die mobile Anwendungsentwicklung PAnsiChar
nicht unterstützt, wurden die Methoden der Klasse TStringBuilder entfernt, die Argumente vom Typ PAnsiChar
akzeptieren:
TStringBuilder* __fastcall Append(const char * Value)/* overload */;
TStringBuilder* __fastcall Append(const System::RawByteString Value)/* overload */;
In diesem Fall arbeitet ähnlicher C++-Code wie der im folgenden Codefragment nicht mehr wie erwartet:
std::auto_ptr<TStringBuilder> sb(new TStringBuilder());
// ...
sb->Append("Hello");
Im obigen Beispiel ruft C++ für mobile Anwendungen die Methode Append
, die einen bool
-Parameter erwartet, im Hintergrund auf. Dieser Code müsste folgendermaßen lauten, damit er auf Desktop- und mobilen Plattformen funktioniert:
std::auto_ptr<TStringBuilder> sb(new TStringBuilder());
// ...
sb->Append(String("Hello"));
ShortString: TTypeInfo.Name
ShortString
wird nicht in Delphi für mobile Anwendungen unterstützt. Daher wurden alle Deklarationen, in denen ShortString
für Desktop-Plattformen, wie TTypeInfo
, verwendet wurde, ebenfalls geändert. Der Member Name
ist bei mobilen Anwendungen ein einfacher Byte
-Typ. Daher schlägt der folgende C++-Code auf mobilen Plattformen fehl:
static System::UTF8String getTypeInfoName(System::Typinfo::PTypeInfo ti)
{
return System::UTF8String(ti->Name);
}
Die obige Funktion gibt für mobile Anwendungen im Hintergrund einen String mit einem Byte-Wert, nicht den Namen des Typs, zurück. Der Code müsste folgendermaßen lauten, damit er auf Desktop- und mobilen Plattformen funktioniert:
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
}
Typumwandlung
In mobilen C++-Anwendungen wird keine C-artige Typumwandlung für Zeiger zu Klassen im Delphi-Stil, wie TButton oder TSpeedButton, unterstützt.
Das folgende Codefragment ist beispielsweise falsch:
void Callback(void* p)
{
((TButton*)p)->Enable = true;
}
Stattdessen sollten Sie den Operator reinterpret_cast
verwenden, der beliebige Zeigertypen in beliebige andere Zeigertypen, sogar von unabhängigen Klassen, konvertiert. Überarbeiten Sie das obige C++Codefragment wie folgt, damit Sie es für mobile C++-Plattformen verwenden können:
void Callback(void* p)
{
reinterpret_cast<TButton*>(p)->Enable = true;
}
C++11-Features
Die C++-Compiler für iOS (BCCIOSARM und BCCIOSARM64) verwenden die im iOS-SDK enthaltene STL (nicht die Dinkumware Standard-C++-Bibliothek, die von C++-Anwendungen auf Desktop-Plattformen unterstützt wird).
Die C++-Compiler unterstützen nur die C++11-Haupt-Features, die vom BCC64-Compiler implementiert werden. iOS-Compiler unterstützen die C++11-Standardbibliotheks-Features nicht, die für unsere anderen C++-Compiler (in der Win64-Standardbibliothek, in Boost und in C++11-Headern, wie regex
, chrono
usw.) verfügbar sind.
Weitere Informationen über C++11-spezifische Header finden Sie unter:
- C++11
- C Standard Library header files (EN) (C++11-spezifische Header sind mit "(since C11)" gekennzeichnet)
Verwenden von starken Aliasen in C++
In früheren Versionen von Delphi wurden integrierte Typen, wie NativeInt, NativeUInt und WordBool, integrierten C++-Typen zugeordnet. In neueren Versionen von Delphi werden diese Typen als starke Aliase, wie TAlphaColor oder TImageIndex behandelt. Damit C++ mit dieser Änderung kompatibel bleibt, erstellt C++ mit einem Klassen-Wrapper ebenfalls starke Aliase.
Um z. B. NativeInt zu verarbeiten, müssen Sie den Typ explizit angeben (NativeInt). Sehen Sie sich zur Klärung die folgenden Beispiele an:
NativeInt i = 10; // error
NativeInt i = NativeInt(10); // OK
Verwenden des Operators "delete"
Angenommen Ihr Code enthält den Operator delete
:
delete ptr
wobei ptr
ein Zeiger auf den freizugebenden Speicherblock ist.
Auf mobilen Plattformen ruft der C++-delete
-Operator nicht immer einen Objektdestruktor auf. Der delete
-Operator arbeitet folgendermaßen:
- Wenn
ptr
auf eine Klasse im Delphi-Stil zeigt, dekrementiert derdelete
-Operator lediglich den Referenzzähler RefCount (die Anzahl von Referenzen auf diese Klasseninstanz). Der Objektdestruktor wird nur aufgerufen, wenn keine Referenzen auf dieses Objekt vorhanden sind. - Wenn
ptr
auf keine Klasse im Delphi-Stil zeigt, arbeitet derdelete
-Operator genauso wie in C++-Anwendungen auf Desktop-Plattformen.
Auflösen von Linker-Warnungen zu String-Literalen
Der folgende Linker-Fehler:
Error: "__ZN6SystemplEPKwRKNS_13UnicodeStringE", referenced from ...
zeigt an, dass Ihr Code ein wchar_t-Konstantenliteral, das (mit dem +
-Operator) einem UnicodeString hinzugefügt wurde, enthält.
Ändern Sie das Konstantenliteral in char16_t, um diesen Fehler zu vermeiden. Verwenden Sie das Makro _D(<Literal-String>)
für String-Literale, die mit UnicodeString interagieren.
Ersetzen Sie beispielsweise:
L"Hello " + System::String("world!")
durch
_D("Hello ") + System::String("world!")
Informationen zu den mobilen Plattformen finden Sie unter Die String-Literale char16_t und wchar_t auf OS X und iOS.
Für mobile Plattformen sind "Defines" erforderlich
Damit Ihr Projekt für mobile Plattformen und Desktop-Plattformen compiliert werden kann, stellen Sie Ihrer Projektimplementierung und den vorcompilierten Header-Dateien (z. B. "Project.cpp" und "ProjectPHC.h") das folgende #ifdef
-Fragment voran:
#ifdef _WIN32
#include <tchar.h>
#else
typedef char _TCHAR;
#define _tmain main
#endif
Entfernen Sie FireMonkey-Komponenten, die nicht von den mobilen C++-Compilern unterstützt werden
Komponente für Desktop-Plattformen |
Komponente(n) für mobile Plattformen |
---|---|
TMainMenu, TPopupMenu | TToolBar, TSpeedButton, TPopup |
Im Folgenden finden Sie Einzelheiten zum Ersetzen dieser nicht unterstützten Typen.
TMainMenu oder TPopupMenu
Diese Komponenten werden auf mobilen Plattformen nicht unterstützt. Für die Migration Ihres C++-Desktop-Codes zu mobilem Code sollten Sie TMainMenu oder TPopupMenu aus dem Code entfernen und stattdessen die folgenden, auf mobilen Plattformen unterstützten Komponenten verwenden:
So erstellen Sie ein Menü mit TPopup:
- Wählen Sie in der Tool-Palette die Komponente TToolBar aus, und ziehen Sie sie in den Formular-Designer.
- Wählen Sie in der Tool-Palette die Komponente TSpeedButton aus, und legen Sie sie auf der TToolBar-Komponente ab.
- Wählen Sie im Formular- Designer die SpeedButton-Komponente aus, und wählen Sie dann im Objektinspektor in der Eigenschaft StyleLookup den Eintrag buttonstylelabel aus.
-
- Weitere Einzelheiten zum Auswählen eines Stils in geräteübergreifenden Anwendungen finden Sie unter Mobile-Tutorial: Verwenden von Schaltflächen-Komponenten mit unterschiedlichen Stilen (iOS und Android).
-
- Wählen Sie in der Tool-Palette die Komponente TPopup aus, und ziehen Sie sie in den Formular-Designer.
- Weisen Sie in der Strukturansicht dieses TPopup als untergeordnetes Element von TSpeedButton zu.
- Wählen Sie in der Tool-Palette die Komponente TLabel aus, und ziehen Sie sie in den Formular-Designer.
- Weisen Sie in der Strukturansicht dieses TLabel als untergeordnetes Element von TPopup zu.
- Wählen Sie die TLabel-Komponente aus, und setzen Sie im Objektinspektor die Eigenschaft HitTest auf
True
.
Hinweis: Wiederholen Sie die Schritte 6 bis 8, um mehrere Beschriftungen (TLabel) hinzuzufügen.
-
Implementieren Sie im Quelltext-Editor für die TSpeedButton-Komponente die folgende onClick-Ereignisbehandlungsroutine:
void __fastcall TForm1::SpeedButton1Click(TObject *Sender) { // Open the pop-up window. Popup1->IsOpen = True; }
- Implementieren Sie für jede TLabel-Komponente, die Sie TPopup hinzugefügt haben, die geeigneten onClick-Ereignisbehandlungsroutinen.