-
Notifications
You must be signed in to change notification settings - Fork 197
Flash C Compiler (FlasCC) tips and tricks
The Flash C++ Compiler (FlasCC) provides a complete C/C++ development environment based on GCC that you can use to compile C/C++ code to target Adobe Flash Player and Adobe AIR. Using flascc, you can port virtually any of your existing C/C++ code to the web.
This article contains tips and tricks to help you get started with flascc.
Like most GCC-based toolchains, flascc uses GDB as its debugger. It provides a customized version of GDB to debug flascc-compiled C/C++ code that is running within Flash Player.
Setting the FLASCC_GDB_RUNTIME environment variable
To execute GDB, you must define a FLASCC_GDB_RUNTIME environment variable that contains a fully qualified path to either a standalone debugger version of Flash Player or a web browser in which the debugger version of Flash Player is installed. If the path contains spaces use either double quotes (Windows) or escape spaces with a backslash (Mac).
For example:
- On Windows:
FLASCC_GDB_RUNTIME="/cygdrive/c/Program Files (x86)/Mozilla Firefox/firefox.exe"
- On Mac OS X:
FLASCC_GDB_RUNTIME= export
FLASCC_GDB_RUNTIME=/Users/flex/runtimes/player/11.3/mac/Flash\
Player\ Debugger.app
Using GDB in Firefox If you are using Firefox you may want to extend or disable the plugin hang detection time to avoid the browser prematurely killing the SWF while you are debugging. For more information on how to do this, see the MozillaZine article on this topic.
Connecting GDB to a SWF hosted on a remote site
If your flascc application is running on a remote site (a staging server, for example), set the FLASCC_GDB_RUNTIME environment variable to point to your browser (as described above) and then pass the URL of your remote application to GDB when you start it, for example:
gdb www.mysite.com/games/mygame.html
Debugging SWCs with GDB
When you compile a SWC, you specify a namespace. So, when you debug that SWC, you need to tell GDB which namespace you want using the set as3namespace command. You can debug only one SWC per session. For more information, see the GDB section of docs/Reference.html of your local flascc installation or online.
Using the GDB call command
While debugging with GDB, you can use the call command to invoke a function in your code. This can be an arbitrary function in which you are interested, or it can be a function that you have added strictly for debugging purposes. For example:
(gdb) call dumpValues()
Rerunning a SWF in GDB (and disregarding the associated warnings)
When you rerun a SWF in GDB, you may see a warning like the following:
warning: Temporarily disabling breakpoints for unloaded shared library "remote:0.elf"
You can safely ignore these warnings.
Here is an example of running and rerunning a SWF in GDB:
<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)
Disregarding the "No symbol table is loaded...." message
In certain situations, when you run GDB, you will see the following message:
No symbol table is loaded.... pending on future shared library load
You can safely ignore this warning.
Use monitor eval to view long Strings in GDB GDB does not display ActionScript 3 Strings in the regular list of locals if the String is longer than 80 characters. To view these Strings, use the monitor eval command.
For example, monitor eval myLongVariable
displays the String value regardless of the length.
When you’re done debugging and ready to optimize, consider the following tips.
Generating a fully optimized application
By default, the flascc version of GCC produces ActionScript ByteCode (ABC). This is adequate for most of the development cycle, when fast compile times are what you need. However, for full optimization, use the -emit-llvm or -O4 options when invoking GCC. These options result in LLVM bitcode, which creates a Link Time Optimized (LTO) build. Although it takes longer to compile with these switches, you get a final fully-optimized build with everything compiled as LLVM bitcode. For example, the following command lines create a fully optimized build:
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
Using GCC to generate a SWC
When you use GCC to generate a SWC you must use the -emit-swc= option to specify the AS3 package name that will contain the generated code and the internal flascc boilerplate code. This lets you link multiple flascc-generated SWCs into one SWF without any function or class collisions. The following example is from /tutorials/05_SWC/makefile:
"$(FLASCC)/usr/bin/g++" -O4 MurmurHash3.cpp as3api.cpp main.cpp
-emit-swc=sample.MurmurHash -o MurmurHash.swc
For more information, see Building SWCs in docs/Reference.html of your local flascc installation.
Optimizing SWC and SWF size
Although GCC includes many options to minimize output size, the following are the most common techniques:
- Use the GCC -O4 option to generate LLVM bitcode and create a fully optimized build.
- Use an exports file to customize what is included in the build. For an example, see /tutorials/12_Stage3D/exports.txt.
- Experiment with the various optimization options that llvm provides (such as -Os)
Targeting an older SWF
The SWF version determines which version of the AIR and Flash Player APIs are available. For example, SWF 17 equates to AIR 3.4 and Flash Player 11.4; if you specify SWF 16, your application will have access to only the AIR 3.3 and Flash Player 11.3 APIs. If, for some reason, you want to target an older SWF version, use the GCC -swf-version= option (the current default is SWF version 17, so to change it to SWF version 16, you'd specify the following:
-swf-version=16
For more information on the mapping between SWF version and Flash Player version, see Creating the extension descriptor file.
Using the C++ wrappers to Flash classes
Flascc provides a set of header files that wrap the Flash top-level classes (for example, Number and Array), as well as the Flash class library (for example, flash.display.Stage and flash.display.Stage3D). These wrappers provide access to all methods, properties, and events of the corresponding ActionScript classes. For more information, see Interop Between C/C++ And ActionScript in docs/Reference.html of your flascc installation. The wrappers are also used in tutorials/12_Stage3D/stage3d.cpp.
Customizing the default preloader
Flascc applications automatically include a simple preloader that displays as the SWF loads. You can create a customized preloader to use with your flascc application. This is explained in the flascc Reference Guide, available in the /docs directory of your flascc installation.
Adjust Java memory allocation
Although it is strongly recommended that you use 64-bit Java with flascc, some developers have been able to use 32-bit Java for certain, small applications. In this case, if the machine has limited memory, you may need to reduce the Java heap specification (the default is –jvmopt="-Xmx1500m"
) to a smaller number, for example, –jvmopt="-Xmx256m". You can do this when invoking GCC in the makefile. For example:
gcc -jvmopt="-Xmx256M" hello.c -o hello.exe
Conversely, if you are running 64-bit Java and your machine has memory to spare, you may want to increase the Java heap size.
64-bit Java is available from the Oracle software downloads page.
Here are some additional tips for using flascc.
Using a class in a SWC file as the Console
When you link against a SWC, you must specify the object that will be the Console.
You should call CModule.vfs.setConsole(this); before the call to initLib() in the ActionScript file and also include an implementation of write() that looks something like this:
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;
}
For another example, see Console.as in the 04_Animation tutorial.
Customizing SWF dimensions
To specify the SWF dimensions, pass the -swf-size=widthxheight
flag to GCC; for example: -swf-size=200x200.
Defining an import so that you can use Context3d in a function call
To define an import so that you can use Context3D in a function call, use the as3import annotation. The following example snippet is from /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")));
Preventing memory leaks in wrappers for functions that return structs and objects by value
When using the SWIG compiler to create SWCs from your C/C++ header files, note the following:
- By default, the wrappers for functions that return structs and objects by value leak memory. SWIG has no way of knowing by itself when it should free such values, so it's expected that the code that calls the wrapper will free the returned value at the appropriate time.
- Flascc has no standard typemaps for std::string, nor any of the C++ standard library classes. Because of this, many uses of std::string or similar classes in wrappers may not work as expected, and you’ll need to write application-specific typemaps to achieve the desired behavior.
Using as3wig to create a C++ interface
You can use the flascc AS3 Wrapper Interface Generator (as3wig) to create a C++ library interface for existing ActionScript 3 ActionScript ByteCode (ABC). For an example, see /tutorials/12_Stage3D/makefile in your local installation, specifically, the following line:
sdk/usr/lib/as3wig.jar -i AGAL.abc -o AGAL
Creating a custom Console implementation
When your SWF loads, the Console class is the first class to be created and executed. It is an ActionScript class that controls when and how the flascc compiled code is initialized. It is also used by the underlying flascc POSIX implementation as the object that handles read and write requests to the various standard input, output, and error terminal streams. In some cases, you will want to create a custom Console implementation. For example, although you can interact with all of the Flash APIs using the C++ wrappers included in Flash++.h, you might prefer to use pure ActionScript 3 in your Console implementation. For information on the Console class, see the ActionScript API docs in /docs/apidocs/index.html
of your flascc installation. For complete information, see /docs/Reference.html of your flascc installation.
Don't use fsync()
Flascc does not support fsync(). Instead, close the file, which will commit your changes.
Using CModule.startBackground() and CModule.startAsync()
The com.adobe.flascc.CModule ActionScript class contains convenience functions for reading and writing to domainMemory. It also manages any flascc-specific global state (for example, the VFS and POSIX interface implementations). Among other methods, note the difference between the following:
- startAsync() - Calls the libc __start1 function which, in turn, causes main() to execute.
- startBackground() - Creates a background Worker and runs the libc function __start1 within that Worker. This method requires SWF version 18 (Flash Player 11.5) or higher.
For information on the CModule class, see the ActionScript API docs in /docs/apidocs/index.html of your flascc installation.
For further reading, see the Adobe Gaming flascc page.
This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License.