デスクトップ アプリケーションからモバイル アプリケーションへの C++ コードの移行
C++ におけるマルチデバイス アプリケーションについての考慮事項 への移動
このトピックでは、デスクトップ プラットフォーム用に記述された既存の C++ コードを、モバイル プラットフォームで動作するように移行する方法について説明します。
Delphi 言語はモバイル プラットフォーム用に少し変更されました。 これらの変更の多くは、このトピックで説明するように、デスクトップ プラットフォームからモバイル プラットフォームへ C++ コードを移行する際に影響を及ぼします。
目次
C++ モバイル コードの特性
モバイル プラットフォームの C++ アプリケーションの開発時や C++ デスクトップ コードからモバイル コードへの移行時に考慮しなければならない特性がいくつかあります。
文字列型に関して
System.String は C++ の System::UnicodeString 型にマッピングされます。
C++ モバイル コンパイラには、まだ AnsiString、UTF8String、RawByteString、ShortString が用意されています。しかし、これらの型の API はデスクトップ プラットフォームのそれらの C++ 版で提供される API の一部になります。
System.AnsiStringT クラスの以下のメソッドは C++ モバイル コンパイラでは使用できません。
モバイル プラットフォームで使用できない System.AnsiStringT(AnsiString、UTF8String、RawByteString) のメソッド |
---|
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)
|
型キャストに関して
C++ モバイル コンパイラでは、TButton や TSpeedButton などの Delphi 形式のクラスを指すポインタの C 言語のようなキャストをサポートしていません。
たとえば、次のようなコードは間違いです。
void Callback(void* p)
{
((TButton*)p)->Enable = true;
}
代わりに、reinterpret_cast
演算子を使用しなければなりません。この演算子は任意のポインタ型を他の任意のポインタ型(無関係なクラスのポインタでも可)に変換します。上記の C++ コードをモバイル プラットフォームに使用するには、次のように書き直します。
void Callback(void* p)
{
reinterpret_cast<TButton*>(p)->Enable = true;
}
C++11 機能に関して
iOS 用の C++ コンパイラ(BCCIOSARM および BCCIOSARM64)では、(デスクトップ プラットフォームの C++ アプリケーションでサポートされている Dinkumware 標準 C++ ライブラリではなく)iOS SDK に付属している STL を使用します。
iOS 用 C++ コンパイラでは、BCC64 コンパイラで実装されている C++11 のコア機能のみサポートしています。 iOS コンパイラは、標準 C++11 ライブラリ機能をサポートしていません。これは、当社の他の C++ コンパイラ(Win64 ライブラリ、Boost ライブラリ、C++11 ヘッダー内にある、regex
、chrono
、など)で利用できる機能です。
C++11 固有のヘッダーの詳細については、以下を参照してください。
- Modern C++
- C 標準ライブラリ ヘッダー ファイル(C++11 固有のヘッダーは "(since C11)" と表示されています)
C++ の強いエイリアスの使用
Delphi の以前のバージョンでは、NativeInt、NativeUInt、WordBool などの組み込み型を C++ の組み込み型にマッピングしていました。Delphi の新しいバージョンでは、これらの型を強いエイリアスとして扱っています(TAlphaColor や TImageIndex など)。このような変更に対応するために、C++ でもクラス ラッパーを使って強いエイリアスを作成します。
たとえば、NativeInt を扱うには、型(NativeInt)を明示的に指定する必要があります。この点を明確にするために、次のような場合を考えてみましょう。
NativeInt i = 10; // error
NativeInt i = NativeInt(10); // OK
delete 演算子の使用
次のように、コードに delete
演算子が含まれているとしましょう。
delete ptr
ここで、ptr
は、解放するメモリ ブロックのポインタです。
モバイル プラットフォームでは、C++ の delete
演算子は必ずしもオブジェクトのデストラクタを呼び出すわけではありません。delete
演算子は次のように動作します。
ptr
が Delphi 形式のクラスを指している場合、delete
演算子は RefCount(このクラス インスタンスへの参照回数)をデクリメントするだけです。オブジェクトのデストラクタは、このオブジェクトへの参照が他にない場合にのみ呼び出されます。ptr
が Delphi 形式でないクラスを指している場合、delete
演算子の動作はデスクトップ プラットフォームの C++ アプリケーションの場合とちょうど同じです。
文字列リテラルに関するリンカの警告の解決
次のようなエラーがリンカから出力される場合は、
Error: "__ZN6SystemplEPKwRKNS_13UnicodeStringE", referenced from ...
(+
演算子により)UnicodeString に付加されている wchar_t 定数リテラルがコードに含まれていることを示しています。
これを回避するには、この定数リテラルを char16_t に切り替えます。UnicodeString とやり取りする文字列リテラルの場合には、_D(<リテラル文字列>)
マクロを使用することをお勧めします。
たとえば、次のコードを
L"Hello " + System::String("world!")
次のコードに置き換えます。
_D("Hello ") + System::String("world!")
モバイル プラットフォームの詳細については、「[[C++ におけるマルチデバイス アプリケーションについての考慮事項# macOS および iOS での文字列リテラル char16_t と wchar_t|macOS プラットフォームでの文字列リテラル char16_t と wchar_t]]」を参照してください。
モバイル プラットフォームには条件定義が必要
プロジェクトをデスクトップ プラットフォームだけでなくモバイル プラットフォーム向けにもコンパイルできるようにするには、プロジェクトの実装ファイルとプリコンパイル済みヘッダー ファイル(たとえば "Project.cpp" と "ProjectPHC.h")の前に、次のような #ifdef
ブロックを付け加える必要があります。
#ifdef _WIN32
#include <tchar.h>
#else
typedef char _TCHAR;
#define _tmain main
#endif
C++ モバイルでサポートされていない FireMonkey コンポーネントを削除
デスクトップ アプリケーションで 使用されているコンポーネント |
モバイル プラットフォームで 使用するコンポーネント |
---|---|
TMainMenu、TPopupMenu | TToolBar、TSpeedButton、TPopup |
サポートされていないこれらの型の置き換えの詳細については、以下で説明します。
TMainMenu または TPopupMenu
これらのコンポーネントは、モバイル プラットフォームではサポートされていません。C++ デスクトップ コードをモバイルに移行するには、TMainMenu または TPopupMenu をコードから削除し、モバイルでサポートされている以下のコンポーネントを代わりに使用しなければなりません。
TPopup を使用するメニューを作成するには:
- [ツール パレット]で TToolBar コンポーネントを選択して、フォーム デザイナにドロップします。
- [ツール パレット]で TSpeedButton コンポーネントを選択し、上記のツールバー上にドロップします。
- フォーム デザイナで SpeedButton コンポーネントを選択したあと、[オブジェクト インスペクタ]で StyleLookup プロパティの値フィールドから[buttonstylelabel]を選択します。
-
- マルチデバイス アプリケーションでのスタイル選択の詳細については、「モバイル チュートリアル:さまざまなスタイルを持つボタン コンポーネントを使用する(iOS および Android)」を参照してください。
-
- [ツール パレット]で TPopup コンポーネントを選択して、フォーム デザイナにドロップします。
- [構造]ビューで、この TPopup を TSpeedButton の子にします。
- [ツール パレット]で TLabel コンポーネントを選択して、フォーム デザイナにドロップします。
- [構造]ビューで、この TLabel を TPopup の子にします。
- [オブジェクト インスペクタ]で TLabel を選択し、HitTest プロパティを
True
に設定します。
メモ: ラベルを複数追加する場合は、ステップ 6 ~ 8 を繰り返します。
-
コード エディタで、TSpeedButton コンポーネントに対して以下の onClick イベント ハンドラを実装します。
void __fastcall TForm1::SpeedButton1Click(TObject *Sender) { // Open the pop-up window. Popup1->IsOpen = True; }
- TPopup に追加した TLabel コンポーネントごとに、適切な onClick イベント ハンドラを実装します。