#
例子中的注释已经很详细了,我觉得逐行翻译一下,就完全可以体现出此例子的意义
#include <stdio.h>
#include <string.h>
#include "AS3/AS3.h" //<-----大家注意这货,它提供了C++中调用AS3的方法
int main(int argc, char **argv)
{
/*
flascc使用GCC的inline asm语法来使你可以在C++编写和调用AS3代码。
想更详细地了解汇编规则,可以参考下面的内容
http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
值得说明的是,在flascc里调用采用内联汇编的方式调用AS3,会有一些限制。
在内联汇编中,你不能够编写AS3类。但是,你可以编写C++类。
下面的汇编语句块声明了一个AS3变量,并且将它打印出来。因为这个汇编语句块并没使用这个变量。所以,这个变量必须被标记为volatile ,否则GCC会把它优化掉。并且,这个trace并不会出现在SWF的控制台中,trace的输出是在一个flashlog文件里。想知道如何开启一个trace的输出,可以参考这里
http://kb2.adobe.com/cps/403/kb403009.html
*/
inline_as3(
"var foo:int = 42;\n"
"trace(\"This is inline AS3: \" + foo);\n"
: :
);
/*
汇编语句块允许你输入和输出参数。这样的话,我们就可以很容易地在两个语言间进行交互了。但是,并不是所有的C++类型都能够在AS3中找到对应的。可以参考下面的映射
C类型 AS3类型
int32 int
int64 需要特殊处理
float32 Number
double Number
pointer int
下面,我们来尝试将一个正数取反。
*/
int someint = 123;
int intresult = 0;
inline_as3(
"%0 = -%1;\n"
: "=r"(intresult) : "r"(someint)
);
//回到C语言环境时,我们可以打印这两个值。
printf("-%d is %d\n", someint, intresult);
//使用AS3开方
double somenumber = 45.0;
double result = 0.0;
inline_as3(
"%0 = Math.sqrt(%1);\n"
: "=r"(result) : "r"(somenumber)
);
// 打印
printf("sqrt of %f is %f\n", somenumber, result);
// 使用AS3对行64位整数相乘
unsigned long long somelonglong = 0x243F6A8885A308D3ULL; // 64 fractional pi bits
double piapprox = 0.0;
inline_as3(
//转换为uint是因为1%和2%在AS3中将会被表示为int
"%0 = 3 + uint(%1) / 0x100000000 + uint(%2) / 0x10000000000000000\n"
: "=r"(piapprox) : "r"((unsigned)(somelonglong >> 32)), "r"((unsigned)somelonglong));
printf("pi approx is %.15f\n", piapprox);
//
unsigned hi32, lo32;
inline_as3(
"%0 = uint(Math.sqrt(2) * 0x100000000); %1 = uint(Math.sqrt(2) * 0x10000000000000000)\n"
: "=r"(hi32), "=r"(lo32));
somelonglong = ((unsigned long long)hi32 << 32) | lo32;
printf("52 fractional bits of sqrt(2): %llx\n", somelonglong); // only 52 bit mantissa in double!
/*处理C字符串的话,要麻烦一点。虽然它们不能够自动转换为AS3中的string对象,但是汇编语句块提供了一些帮助函数。
*/
const char* words[] = {"flascc", "is", "awesome!"};
int i;
for(i=0; i<3; i++) {
inline_as3(
"trace(\"trace: \" + %0 + \": \" + CModule.readString(%1, %2));\n"
: : "r"(i), "r"(words[i]), "r"(strlen(words[i]))
);
}
/*那,我们再来看看,如何将一个AS3的string对象转给C/C++代码呢? 因为flascc使用ByteArray来存储,所以我们需要malloc()一些BypteArray的空间。并且复制字符串数据到里面。
mallocString帮助函数接受一个AS3 string对象并且会将它的一份拷贝放到flascc的堆上。这样的话,当用完以后,可以使用C中的free函数进行释放。
下面的代码还演示了两个汇编代码块之间的变量的可用性。
*/
inline_as3("var as3words = ['Interop', 'is', 'easy!'];\n");
char* wordptrs[] = {NULL, NULL, NULL};
for(i=0; i<3; i++) {
inline_as3(
"var stringptr:int = CModule.mallocString(as3words[%0]);\n"
"CModule.write32(%1, stringptr);\n"
: : "r"(i), "r"(&wordptrs[i])
);
}
for(i=0; i<3; i++) {
printf(">>> %s\n", wordptrs[i]);
free(wordptrs[i]);
}
}
完了,可见,使用内联方式调用AS3代码,感觉是比较鸡肋的。 但由于目前对FLASCC了解得不够深入。 不作过多评价。
打开samples/01_HelloWorld,你会发现,只有一个hello.c和Makefile文件。
打开hello.c,你会更加吃惊,因为只有
#include <stdio.h>
int main(int argc, char **argv)
{
printf(“Hello World”);
//这是我加上的,原文没有。
return 0;
}
这完全就是一个普普通通的C语言HELLO WORLD程序。
在程序中,夹杂着一段注释
// flascc comes with a normal BSD libc so everything you would expect to
// be present should work out-of-the-box. This example just shows a
// simple message formatted using printf.
//
// When compiled as a projector this message will be to stdout just like
// a normal commandline application. When compiled to a SWF it will be
// displayed in a textfield on the stage. This behavior is overrideable
// as you will see in later samples.
大概就是说FLASCC使用的是常规的BSD libc。如果是使用普通的C库,那你的代码编写起来,没有任何区别。
使用FLASCC编译时,可以编译成三种东西, 一种是Projector程序,这种程序是在Cygwin下可以执行的EXE文件。
一种是swf,这种就是直接可以用FP播放的了。 还有一种是SWC,可以提供给AS3调用。
代码本身没有太多特别的。 我们来看看Makefile的内容。
T01: check
@echo "-------- Sample 1 --------"
@echo && echo "First let's compile it as a projector:"
"$(FLASCC)/usr/bin/gcc" $(BASE_CFLAGS) hello.c -o hello.exe
@echo && echo "Now lets compile it as a SWF:"
"$(FLASCC)/usr/bin/gcc" $(BASE_CFLAGS) hello.c -emit-swf -swf-size=200x200 -o hello.swf
include ../Makefile.common
clean:
rm -f hello.swf hello *.bc *.exe
这个Makefile中,第一次是将这个编译为hello.exe,即刚刚说到的Projector程序。 第二次是编译为hello.swf.
可以看出,二者都使用了相同的CFLAGS标记。 我们打开Makefile.common可以看到,BASE_CFLAGS实际上是
-Werror -Wno-write-strings -Wno-trigraphs
我们暂时不关注这个。 我们来看看,如果想生成一个projector程序,则和GCC下编译一个普通的EXE程序没有区别。而如果是想编译为SWF,则需要手动指定一些额外的参数。
-emit-swf -swf-size=200x200
-emit-swf表示告诉编译器,目标文件是swf
-swf-size=200x200则告诉编译器,最终生成的目标SWF的舞台大小。
总的来说,这个比较简单,虽然没有什么可看的。还是贴一下效果图。

Windows版本的FlasCC需要用到Cygwin环境。 Cygwin环境是一个类Linux的环境。它使得我们可以在Windows下运行基于POSIX标准的系统(如LINUX,BSD,UNIX)的可执行文件。FlasCC绑定了一个Cygwin版本。 你可以使用FlasCC中的run.bat启动它。
下面,我们来看一下,要想在Windows上使用FlasCC的具体步骤
- 解压下载的FlasCC SDK包到你的硬盘上(建议是某个盘的根目录)。如(c:/flascc)
- 需要确定,你的机器上安装了 64位的JAVA。 如果没有安装,可以走这里.http://www.java.com/getjava
- 确保你配置好了JAVA的PATH,如果没有,可以走这里.http://www.java.com/en/download/help/path.xml
- 下载FlexSDK(有些例子需要4.6或者更高版本)。 下载后,解压到你喜欢你的地方。如(c:/flex_sdk)
- 如果你想试着用GDB来调试代码,那需要下载一个DEBUG版本的Flash Player
- 双击run.bat(这个,太简单了)
- 尝试编译 01_HelloWorld,以确保环境没问题了。
- cd 01_HelloWorld
- make FLASCC=/cygdrive/c/flascc/sdk FLEX==/cygdrive/c/flex_sdk
- 执行你的hello.swf文件
使用其它版本的Cygwin
如果你不想使用官方给你的那一个Cygwin,你可以使用最新版本的,并且,你需要以下功能包支持
- make
- libuuid1
- python
- cmake
FlasCC 1.0.1发布说明
- DEBUG版本创建的程序,在运行时不会再报 “THUNK”错误。
- 当连接使用CModule.startAsync()开始时,avm2_uithunk不会再失败了。
- 当一个main函数使用CMoudle.startBackground()作为开始时,也可以使用AS3_GoAsync()了。
- 当使用InMemoryBckingStore 这个AS3 API添加一个路径时,就算是最后带了斜杠,也可以正常工作了。
FlasCC 1.0.0发布说明
Adobe Flash C++ Compiler (FlasCC)使你可以将你的代码完整地导入Flash运行时库:
- 使用你现有的C/C++项目文件和Makefile文件,如果你已经在使用GCC了的话。只需要把你的C++代码用FlasCC重新编译为Flash Player平台的可执行文件就可以了。(SWF或者SWC)
- 你可以使用GDB来调试你在Flash Player中运行的代码,就像你平时使用的GDB一样。
- 你可以通过C/C++访问整个Flash运行时库的API。 包括Stage3D图形加速API。
- 有大量的文档,教程以及将C/C++库(Lua,Box2D,Bullet等)导入到Flash运行时库的例子作为参考。
- FlasCC也可以让你使用C/C++代码来创建SWC库。以供AS3开发者使用。 可以使用SWIG来自动创建C/C++代码的AS3调用接口。
已知问题:
- 使用了多线程的代码,需要FP 11.5或者更高
- 使用了多线程的代码,目前不能被Google Chrome(PPAPI)支持。不过,Google和Adobe正在努力解决问题,在将来的Chrome版本中,将解决这个问题。
- stat系列的系统调用不会提供有意义的值。如st_time,st_mtime,st_ctime等。
- 当尝试列出一个对象文件(object file)或者归档文件(archive)中的符号表时,nm会错误地标记一个本地符号为外部符号。
- 当在有限的内存环境下。需要显式地减少JVM的内存消耗。可以通过 gcc/g++时,传入jvmopt参数。 比如:gcc -jvmopt=-Xmx1000M input.c –o output
- 一些对SOCKET进行监控的程序(比如防火墙或者杀毒软件),将会阻碍GDB调试。
- 对于Windows用户,有很多软件都可能导致Cywin和FlasCC的安装或者启动失败。
- 在例子程序中的Makefile所使用的“FLASCC”和“FLEX”变量是绝对路径
FlasCC是Adobe的Alchemy 2的商标名。 早在Alchemy 1.0的时代,Adobe就成功地实现了将纯C/C++编写的程序,编译为SWF和SWC。 而在Alchemy 1.0的时代,是要收费的。
到Alchemy 2.0的时候,Adobe正式推出,并成为了游戏开发工具包的主力成员。 第一次推行的时候,FlasCC是要收费的,按每个产品的Title进行利润抽成。 高达 9%. 这一举动将很多开发商挡在了门外。 因为作为了一个新兴的编译器,以及,编译导向为Adobe自己的平台。 更多开发商在这里停步了。因为特别是国外一些大作,其作品都是由很多大师级引擎拼装而成的。 比如UDK,ScaleForm,Havok等等。 它们中很多引擎已经是抽成模式了。 现在Adobe还要来抽成,还抽了9%。 这就有点过了。
Adobe得知这样下去,将会很艰难,于是改变战略,将FlasCC作为了免费工具。
而由于这一举动,使得早先就使用FlasCC的Unity3D引擎受到了损失。 因为Unity3D引擎之前用FlasCC是交了钱的。 现在又不交钱了,好像Adobe也没有要退钱的意思。 最后,最新版的Unity3D不再提供导出为SWF的功能。 官方给出的原因是说Adobe对Stage3D的发展方向不确定,于是不再打算支持。
而大名鼎鼎的UDK则一如既往,提供了一个网页版的示例DEMO。 目前就放在了FlasCC的推广页上。 可以直接传送,耐心等待一会儿就可以出现一个场景漫游的效果了。
http://www.unrealengine.com/flash/
UDK放出这个DEMO很久了,但是DEMO一直没有更新。 这应该是其它问题了。也不好猜测。
而FlasCC本身是很OK的,特别是到了目前FlasCC 1.0.1版本。 我通过对文档和例子的研究。大概发现FlasCC可以完成以下事情。
一、将先前的C++库直接编译为SWC,供AS3项目使用。 比如一些纯C++写的跨平台物理引擎(BOX2D,BULLET等等)
二、如果想提供一个真正的多线程环境,那可以使用C++编写基于POSIX标准的线程库,供SWC使用。
三、一些效率要求较高的地方,比如寻路,排序等,可以使用C++编写,导出为SWC,供AS3项目使用。
四、可以使用OPENGL编写图形引擎,编译为SWC,而采用AS3进行逻辑开发,做微端或者页游。 OPENGL很多人都熟悉,同时,GLSL比AGAL好写得多,并且C++编写的效率较高(要在LLVM上运行)。 结合二者的优点,可以让一个端游团队快速转向页游或者端游,如果效率优化足够,可以直接到达手游。
五、已经成熟的游戏,想改微端或者页游,可以更换其图形层(如果是D3D写的,如果是OPENGL,就容易多了)。再编译为AIR或者SWF就可以了。