Migrating C++ Code to Mobile from Desktop
Go Up to C++ Considerations for Multi-Device Applications
This topic describes how to migrate existing C++ code written for desktop platforms so that it works on mobile platforms.
The Delphi language has undergone some changes for mobile platforms. Many of these changes affect porting C++ code from desktop platforms to mobile platforms, as described in this topic.
Contents
Peculiarities of C++ Mobile Code
There are some peculiarities or "gotchas" that you should consider when you are developing your C++ applications for mobile platforms or when you are migrating C++ desktop code to mobile code.
About String Types
System.String maps to the C++ System::UnicodeString type.
C++ Mobile provides AnsiString, UTF8String, RawByteString and ShortString. But the API of these types is a subset of that provided in the C++ versions of these types for desktop platforms.
The following methods of the System.AnsiStringT class are not available in С++ Mobile:
Methods of System.AnsiStringT (AnsiString, UTF8String, RawByteString) that are not available in mobile platforms |
---|
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)
|
About Type Casting
C++ mobile does not support C-like casting for pointers to Delphi-style classes, such as TButton or TSpeedButton.
For example, the following code snippet is incorrect:
void Callback(void* p)
{
((TButton*)p)->Enable = true;
}
Instead, you should use the reinterpret_cast
operator, which converts any pointer type to any other pointer type, even of unrelated classes. To use the above C++ code snippet for mobile platforms, rework it as follows:
void Callback(void* p)
{
reinterpret_cast<TButton*>(p)->Enable = true;
}
About C++11 Features
The C++ compilers for iOS (BCCIOSARM and BCCIOSARM64) use the STL included with the iOS SDK (not the Dinkumware Standard C++ Library, which is supported by C++ applications on desktop platforms).
The C++ compilers for iOS support only the core C++11 features that are implemented by the BCC64 compiler. iOS compilers do not support the standard C++11 library features, which are available for our other C++ compilers (in the Win64 standard library, in the Boost, and in C++11 headers, such as regex
, chrono
, and so forth).
For more information about C++11-specific headers, see:
- Modern C++
- C Standard Library header files (C++11-specific headers are marked as "(since C11)")
Using C++ Strong Aliases
Earlier versions of Delphi mapped built-in types such as NativeInt, NativeUInt, and WordBool to C++ built-in types. Newer versions of Delphi handle these types as strong aliases, such as TAlphaColor or TImageIndex. In order to be compatible with the change, C++ also creates strong aliases using a class wrapper.
For example, to handle a NativeInt, you need to explicitly specify the type (NativeInt). To clarify, consider the following cases:
NativeInt i = 10; // error
NativeInt i = NativeInt(10); // OK
Using the delete Operator
Let us consider that your code contains the delete
operator:
delete ptr
where ptr
is a pointer to the memory block to be released.
In mobile platforms, the C++ delete
operator does not always call an object destructor. The delete
operator works in the following way:
- If
ptr
points to a Delphi-style class, thedelete
operator merely decrements the RefCount (the number of references to this class instance). The object destructor is invoked only if there are no other references to this object. - If
ptr
points to a non-Delphi-style class, thedelete
operator works exactly the way it does in a C++ application on desktop platforms.
Resolving Linker Warnings about String Literals
The following error from the linker:
Error: "__ZN6SystemplEPKwRKNS_13UnicodeStringE", referenced from ...
indicates that your code contains a wchar_t constant literal being added (via the +
operator) to a UnicodeString.
The workaround is to switch the constant literal to a char16_t. We recommend that you use the _D(<lit-string>)
macro for string literals interacting with UnicodeSTring.
For example, replace:
L"Hello " + System::String("world!")
with
_D("Hello ") + System::String("world!")
For information about the mobile platforms, see String Literals char16_t and wchar_t on the macOS Platform.
Defines Required for Mobile Platforms
To make your project compile for mobile platforms as well as desktop platforms, prepend your project implementation and precompiled header files (for example, "Project.cpp" and "ProjectPHC.h") with the following #ifdef
snippet:
#ifdef _WIN32
#include <tchar.h>
#else
typedef char _TCHAR;
#define _tmain main
#endif
Eliminate FireMonkey Components that Are Not Supported on C++ Mobile
Component Used in Desktop Platforms |
Component(s) to Use in Mobile Platforms |
---|---|
TMainMenu, TPopupMenu | TToolBar, TSpeedButton, TPopup |
Details follow about replacing these unsupported types.
TMainMenu or TPopupMenu
These components are not supported in mobile platforms. To migrate your C++ desktop code to mobile, you should remove TMainMenu or TPopupMenu from your code, and use instead the following mobile-supported components:
To create a menu that uses TPopup
- Select the TToolBar component in the Tool Palette, and drop it on the Form Designer.
- Select the TSpeedButton component in the Tool Palette and drop it on the ToolBar.
- Select the SpeedButton component on the Form Designer, and then select buttonstylelabel in the StyleLookup property in the Object Inspector.
- For more details about selecting a style in multi-device applications, see Mobile Tutorial: Using a Button Component with Different Styles (iOS and Android).
- Select the TPopup component in the Tool Palette, and drop it on the Form Designer.
- In the Structure View, make this TPopup a child of the TSpeedButton.
- Select the TLabel component in the Tool Palette, and drop it on the Form Designer.
- In the Structure View, make this TLabel a child of the TPopup.
- Select the TLabel, and in the Object Inspector, set the HitTest property to
True
.
Note: To add several labels, repeat Steps 6 to 8.
-
In the Code Editor, for the TSpeedButton component, implement the following onClick event handler:
void __fastcall TForm1::SpeedButton1Click(TObject *Sender) { // Open the pop-up window. Popup1->IsOpen = True; }
- For each TLabel component that you have added to the TPopup, implement the appropriate onClick event handlers.