必要条件

この記事に必要な予備知識

過去にコンパイラを使用した経験があると、この記事を最大限に活用できます。

ユーザーレベル

中級

原文 作成日: 2012/12/3
Flash C++ Compiler (FlasCC) tips and tricks

Flash C++ コンパイラ (FlasCC) は、GCC に基づいた、C/C++ コードをFlash Player と Adobe AIR をターゲットとしてコンパイルできる、完全な C/C++ 開発環境を提供します。flascc を使用すると、実質的にすべての既存の C/C++ コードを Web に移植できます。

この記事では、flascc を使用する上でのコツとヒントを提供します。

GDB によるデバッグのヒント

ほとんどの GCC ベースのツールチェーンと同様に、flascc は GDB をデバッガとして使用します。カスタマイズされた GDB が提供され、Flash Player で実行中の、flascc でコンパイルした C/C++ コードをデバックできます

FLASCC_GDB_RUNTIME 環境変数を設定する

GDB を実行するには、スタンドアロンデバッガバージョンの Flash Player またはデバッガバージョンの Flash Player がインストールされた Web ブラウザへの完全修飾パスを含む FLASCC_GDB_RUNTIME 環境変数を定義する必要があります。パスにスペースが含まれる場合は、二重引用符を使用 (Windows) するか、バックスラッシュでスペースをエスケープ (Mac) します。

たとえば、次のように行います。

  • Windows:
FLASCC_GDB_RUNTIME="/cygdrive/c/Program Files (x86)/Mozilla Firefox/firefox.exe"
  • Mac OS X:
FLASCC_GDB_RUNTIME= export FLASCC_GDB_RUNTIME=/Users/flex/runtimes/player/11.3/mac/Flash\ Player\ Debugger.app

Firefox で GDB を使用する

Firefox を使用している場合、デバッグ中の SWF をブラウザが途中で終了しないように、プラグインの中断の検出時間を延長または無効化することができます。この方法については、このトピックに関する MozillaZine の記事を参照してください。

リモートサイトにホスティングされた SWF に GDB を接続する

flascc アプリケーションをリモートサイト (ステージングサーバーなど) で実行している場合、FLASCC_GDB_RUNTIME 環境変数がブラウザに指すように設定し (上記参照)、リモートアプリケーションが開始したときに、その URL を GDB に渡します。

gdb www.mysite.com/games/mygame.html

GDB を使って SWC をデバッグする

SWC をコンパイルするとき、名前空間を指定します。そのため、その SWC をデバッグする場合、as3namespace コマンドを使用して利用したい名前空間を GDB に指示する必要があります。セッション当たり、デバッグできる SWC は 1 つのみです。詳細は、ローカル flascc インストールまたはオンラインdocs/Reference.html にある GDC セクションを参照してください。

GDB call コマンドを使用する

GDB でデバッグしている最中に、call コマンドを使用して、コード内の関数を呼び出すことができます。これは、関心のある任意の関数、またはデバッグの目的のみに追加した関数など任意の関数です。たとえば、次のように実行します。

(gdb) call dumpValues()

GDB で SWF を再実行する (その際、関連付けられた警告を無視する)

GDB で SWF を再実行する場合、次のような警告が表示される場合があります。
「warning:Temporarily disabling breakpoints for unloaded shared library "remote:0.elf"」

これらの警告は、無視しても安全です。

次は、GDB で SWF を実行および再実行する例です。

<path>/sdk/usr/bin/gdb call.swf GNU gdb (GDB) 7.3 Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=x86_64-apple-darwin10 --target=avm2-elf". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... (gdb) b main No symbol table is loaded. Use the "file" command. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (main) pending. (gdb) r Starting program: call.swf 0xdddddddd in ?? () Breakpoint 1, 0xf0000247 in main (argc=0, argv=0x200ff0) at call.c:66 66 int s = 2; (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y warning: Temporarily disabling breakpoints for unloaded shared library "remote:0.elf" Starting program: call.swf 0xdddddddd in ?? () Breakpoint 1, 0xf0000247 in main (argc=0, argv=0x200ff0) at call.c:66 66 int s = 2; (gdb)

「No symbol table is loaded....」メッセージを無視する

特定の状況において、GDB を実行する際に、次のようなメッセージが表示されます。

No symbol table is loaded.... pending on future shared library load

この警告は、無視しても安全です。

monitor eval <longLocalVariableString> 使って、GDB で長い文字列を表示する

GDB は、ローカルの通常のリスト内に、80 文字を超えるActionScript 3 の文字列は表示しません。これらの文字列を表示するには、monitor eval コマンドを使用します。

たとえば、monitor eval myLongVariable は、長さに関係なく、文字列の値を表示します。

最適化のヒント

デバッグを終了し、最適化を行う準備ができたら、以下のヒントを検討します。

完全に最適化されたアプリケーションを生成する

デフォルトでは、flascc バージョンの GCC は、ActionSciprt ByteCode (ABC) を作成します。これは、素早くコンパイルすることが必要である場合、ほとんどの開発サイクルには十分な動作です。ただし、完全な最適化の場合、GCC を呼び出す際に、-emit-llvm オプションまたは -O4 オプションを使用します。これらのオプションによって、リンク時間が最適化された (LTO) ビルドを作成する LLVM ビットコードが作成されます。これらのスイッチでのコンパイルにはより長い時間が掛かりますが、すべてが LLVM ビットコードとしてコンパイルされた、完全に最適化された最終ビルドを得ることができます。たとえば、次のコマンドラインは、完全に最適化されたビルドを作成します。

gcc test.c -emit-llvm -c -o test.o gcc test.c -O4 -c -o test.o gcc test.c -emit-llvm -emit-swf -o test.swf gcc test.c -O4 -emit-swf -o test.swf

GCC を使って SWC を生成する

GCC を使って SWC を作成する場合、 -emit-sec= オプションを使用して、生成されたコードと内部 flscc 定型コードを含む AS3 パッケージ名を指定する必要があります。これにより、flascc によって生成される複数の SWC を、関数またはクラスが衝突することなく 1 つの SWF にリンクすることができます。次の例は、/tutorials/05_SWC/makefile から抜粋されたコードです。

"$(FLASCC)/usr/bin/g++" -O4 MurmurHash3.cpp as3api.cpp main.cpp -emit-swc=sample.MurmurHash -o MurmurHash.swc

詳細は、ローカルにインストールされた flascc のdocs/Reference.html にある「Building SWCs」を参照してください。

SWC と SWF のサイズを最適化する

GCC には出力サイズを最小限に抑えるためのオプションが多数含まれていますが、最も一般的なテクニックを次に示します。

  • GCC -O4 オプションを使って LLVM ビットコードを生成し、完全に最適化されたビルドを作成します。
  • exports ファイルを使って、ビルドに含まれるものをカスタマイズします。例として/tutorials/12_Stage3D/exports.txt を参照してください。
  • llvm が提供するさまざまな最適化オプション (-Os など) 試します。

古い SWF をターゲットする

SWF バージョンによって、利用できる AIR と Flash Player API のバージョンが決定します。たとえば、SWF 17 は AIR 3.4 と Flash Player 11.4 に相当します。SWF 16 を指定すると、アプリケーションは AIR 3.3 と Flash Player 11.3 API のみにアクセスできます。何らかの理由で、古い SWF バージョンをターゲットする場合は、GCC の -swf-version= オプションを使用します。現在のデフォルトは SWF バージョン 17 であるため、SWF バージョン 16 に変更する場合は、次のように指定します。
-swf-version=16

SWF バージョンと Flash Player バージョンのマッピングについての詳細は、「拡張記述ファイルの作成」を参照してください。

Flash クラスに C++ ラッパーを使用する

Flascc は、Flash のトップレベルクラス (Number や Array など) をラップする一連のヘッダーファイルと、Flash クラスライブラリ (flash.display.Stage や flash.display.Stage3D など) を提供しています。これらのラッパーは、すべてのメソッド、プロパティ、および対応する ActionScript クラスのイベントへのアクセスを提供します。詳細は、flascc インストールの docs/Reference.html にある「Interop Between C/C++ And ActionScript」を参照してください。ラッパーは、tutorials/12_Stage3D/stage3d.cpp でも使用されています。

デフォルトのプリローダーをカスタマイズする

Flascc アプリケーションには、SWF が読み込まれるときに表示される単純なプレローダーが自動的に含まれます。カスタマイズされたプリローダーを作成し、flascc アプリケーションで使用することができます。これについては、flascc インストールの /docs ディレクトリにある『flascc Reference Guide』で説明されています。

Java のメモリ割り当てを調整する

flascc では 64 ビット Java を使用することを強くお勧めしますが、一部のデベロッパーは特定の小さなアプリケーションに 32 ビット Java を使用しています。この場合、マシンのメモリが制限されているため、–jvmopt="-Xmx256m" のように、Java のヒープサイズ (デフォルトは –jvmopt="-Xmx1500m") をより小さな数値に抑えることが必要です。これは、makefile で GCC を呼び出す際に行えます。たとえば、次のように行います。

gcc -jvmopt="-Xmx256M" hello.c -o hello.exe

逆に、64 ビット Java を実行していて、マシンに余分なメモリがある場合は、Java ヒープサイズを増やすことができます。

64 ビット Java は、Oracle ソフトウェアダウンロードのページから入手できます。

その他のヒント

次に、flascc を使用する際のその他のヒントをいくつか示します。

SWF ファイルのクラスをコンソールとして使用する

SWC に対してリンクする場合、コンソールとなるオブジェクトを指定する必要があります。
ActionScript ファイルの initLib() を呼び出す前に CModule.vfs.setConsole(this); を呼び出し、次のような write() の実装を含めます。

public function write(fd:int, buf:int, nbyte:int, errno_ptr:int):int { var str:String = CModule.readString(buf, nbyte); trace(str); // or display this string in a textfield somewhere? return nbyte; }

他の例については、04_Animation チュートリアルの Console.as を参照してください。

SWF のサイズをカスタマイズする

SWF のサ幅と高さを指定するには、GCC に次のような -swf-size=widthxheight フラグを渡します。-swf-size=200x200

関数の呼び出しで Context3D を使用できるように import 文を定義する

関数の呼び出しで Context3D を使用できるように import 文を定義するには、as3import アノテーションを使用します。以下のスニペットは、/tutorials/Example_BulletPhysicsLibrary/bullet.i からの抜粋です。

void positionAndRotateMesh() __attribute__((used, annotate("as3sig:public function positionAndRotateMesh(mesh:*, rigidBody:*):void"), annotate("as3package:org.bulletphysics"), annotate("as3import:flash.geom.Vector3D")));

構造体とオブジェクトを値で返す関数のラッパーで発生するメモリリークを回避する

SWIG コンパイラを使用して C/C++ ヘッダーファイルから SWC を作成する場合、次の点に注意してください。

  • デフォルトでは、構造体とオブジェクトを値で返す関数のラッパーはメモリをリークします。SWIG には、そのような値を解放するタイミングを知る術がないため、ラッパーを呼び出すコードによって、返される値を適切なタイミングで解放することが期待されます。
  • Flascc には、std::string やその他の C++ 標準ライブラリクラスの標準 typemap がありません。このため、ラッパーに std::string や類似するクラスを多数使用すると、期待通りに機能しない可能性があります。思い描いた動作を達成するには、アプリケーション固有の typemap を記述する必要があります。

as3wig を使って C++ インターフェイスを作成する

flascc AS3 ラッパーインターフェイス生成ツール (as3wig) を使って、既存の ActionScript 3 ActionScript バイトコード (ABC) の C++ ライブラリインターフェイスを作成できます。たとえば、ローカルにインストールした /tutorials/12_Stage3D/makefile を参照してください。注目するのは次の行です。

sdk/usr/lib/as3wig.jar -i AGAL.abc -o AGAL

カスタム Console 実装を作成する

SWF が読み込まれると、最初に作成されて実行されるクラスは Console クラスです。これは、flascc がコンパイルしたコードをいつどのように初期化するかを制御する ActionScript クラスです。また、flascc の基盤の POSIX 実装によって、種々の標準入出力およびエラーのターミナルストリームへの、読み書きの要求を処理するオブジェクトとして使用されます。場合によっては、カスタム Console を実装したいことがあるでしょう。たとえば、Flash++.h に含まれる C++ ラッパーを使用すればすべての Flash API を操作することができますが、Console 実装に純粋な ActionScript 3 を使用したい場合です。Console クラスの詳細は、flascc インストールの /docs/apidocs/index.html にある ActionScript API ドキュメンテーションを参照してください。完全な情報は、flascc インストールの /docs/Reference.html を参照してください。

fsync() を使用しないこと

Flascc は fsync() をサポートしていません。代わりに、ファイルを使用して、変更をコミットします。

CModule.startBackground() および CModule.startAsync() を使用する

ActionScript クラスにの com.adobe.flascc.CModule は、domainMemory の読み取りと書き込みを行う便利な関数が含みます。また、このクラスは、flascc 固有のグローバル状態を管理します (VFS と POSIX インターフェイス実装など)。その他のメソッドの中でも、特に次の違いに注意してください。

  • startAsync() - libc __start1 関数を呼び出しを経由して、main() を実行します。
  • startBackground() - バックグラウンド Worker を作成し、その Worker 内で libc 関数 __start1 を実行します。このメソッドには、SWF バージョン 18 (Flash Player 11.5) 以上が必要です。

CModule クラスの詳細は、flascc インストールの /docs/apidocs/index.html にある ActionScript API ドキュメンテーションを参照してください。

次のステップ

さらに、Adobe Gaming flascc ページをご覧ください。