Showing posts with label CrossBridge. Show all posts
Showing posts with label CrossBridge. Show all posts

Wednesday, August 13, 2014

Test Notes on Emscripten

Recently, I tried the Emscripten compiler, which can compile C/C++ to HTML5/JavaScript. Also based on LLVM, it is a similar tool as the Adobe CrossBridge, but targeting a different platform. With Emscripten, it's possible not to write even a single line of JS for creating an HTML5 application. But for CrossBridge, you may still need to write some AS3 to make things work. Emscripten has very good SDL and OpenGL support, so you can compile your SDL/OpenGL application into JS without getting hands dirty of JavaScript.

Emscripten is similar to CrossBridge, in may aspects. For Emscripten, like the CrossBridge, you also need to break the C/C++ main infinite loop and use "emscripten_set_main_loop()" to run the loop content frame by frame. However, CrossBridge supports multi-threads and background workers, which is actually an advantage of AS3 over current JS. Both use similar inline asm (AT&T style) for interlope with the targeting languages. Their ways of dealing with the file system are similar - both use a virtual system to simulate C/C++ reading & writing processes and both provide tools for packaging assets. Besides, both CrossBridge and Emscripten can be used as code obfuscators, Emscripten even use the closure compiler for optimizing and obfuscating the generated JavaScript.

I thought the Emscripten SDK is mature enough. Even Unity3D and Unreal engine are using it for publishing HTML5, after they abandoning FlasCC and the flash platform. Also see the Porting Examples and Demos, especially the amazing Cube2 engine demo (The CrossBridge Cube2 port is not yet rendering correctly). However, in my test, for the latest Emscripten SDK (emsdk-1.21.0-web-64bit.exe), if you want to port your SDL applications or games, very likely, you will fail. That's because the support of SDL, although is working for many cases, is far from complete. What's more, the officially supported SDL version is SDL 1.3, while most old games/application are based on SDL 1.2 and most new ones are based on the latest SDL 2 (There're many API differences among these versions). Many SDL functions are not supported or implemented, such as very commonly used "SDL_DisplayFormat", "SDL_ConvertSurface". So when you compile, you may get "unresolved symbols" warnings and a black screen - the compiled application will just not run. Although there is an unofficial SDL port for Emscripten, I'm not sure whether it is worthy of trying.

Fortunately, Emscripten SDK is under very active development, unlike the almost abandoned CrossBridge. I'm looking forward to a future version with more features and great improvements. By the way, there is an unofficial fork of the CrossBridge SDK, which pulled many things together and collected lots of  examples: https://github.com/crossbridge-community, I'm also watching on the project, hope it will continue to involve.

I think, the same problem for both CrossBridge and Emscripten is, there are not many games/applications written in C/C++ there waiting to be ported to the browser platform, so only a few people are actually using these cross language compilers. The reason is most games written in C/C++ are not designed for the browser platform. So if there exists a tool can compile AS3 to JavaScript, I believe it will be very, very popular. And one factor that Emscripten will be more popular than CrossBridge is that JavaScript is not a suitable language for programming large scale games and applications, but AS3 itself is good enough to handle many large projects.

Sunday, August 3, 2014

Using CrossBridge/FlasCC for Code Obfuscation

One advantage of using CrossBridge is that, because your source code is written in C/C++, it's very hard to decompile.Although some decompilers can give you the decompiled ActionScript code from the swf file, it is impossible to recover the original C/C++ source code. What's more, the decompiled ActionScript code is almost unreadable.

See what the official CrossBridge document says:

FlasCC is not designed to be an obfuscator for either ActionScript or C/C++ code. Although the generated ActionScript bytecode should be no easier to reverse engineer than natively compiled machine code the FlasCC engineering team makes no strong claims about this, nor do they test whether this is true.
By default the mangled C++ name of every source function will be trivially visible in both the decompiled output and also in ActionScript debugger and profilers. To hide the names of any generated C/C++ functions you can pass -fllvm-opt-opt=-strip to gcc so that any function names not listed in your exports.txt file will be renamed to a symbol of the form __unnamed_N. Functions that need to be called from ActionScript, which you must protect by listing in exports.txt, will not be renamed.
So to ensure the encryption strength of CrossBridge, you can just pass the option "-fllvm-opt-opt=-strip" to gcc when compiling, this will obfuscate all the function names. By the way, it's possible to use some C/C++ source code obfuscators first before compiling with CrossBridge.

Links: 
https://forums.adobe.com/message/5121420
http://hecool108.blogspot.com/2013/08/hide-your-key-with-alchemyflascccrossbr.html

Wednesday, July 30, 2014

Migrating from Alchemy to CrossBridge/FlasCC - Interop between C/C++ and ActionScript

Part I - Calling C/C++ functions from AS3

For calling C/C++ functions from AS3, one way is use the "as3sig:" annotation to expose some C/C++ functions to AS3. See the CrossBridge Sample 5 SWC and my previous post http://bruce-lab.blogspot.com/2012/12/migrating-from-alchemy-to-flascc.html. Another way is to use "CModule.callI(CModule.getPublicSymbol("youCfunctionname"), args)", see the Sample 4 Animation, where for C++, you will need "extern" declaration before your function definition to prevent the compiler renaming the function.

Part II - Calling AS3 functions from C/C++

To call build-in AS3 functions, you can either use "inline_as3" (see Sample 2 Interop between C/C++ and ActionScript. Actually, asm was also available in Alchemy, although not officially documented) or the API provided by "AS3.h" and "Flash++.h". You can also define local AS3 functions or equivalent C/C++ functions using the two methods in your C/C++ source file. However, if you want to call an AS3 function outside your C/C++ file, e.g., in the "Main.as/Console.as", you may need to pass the reference of your AS3 function or the function host - your main AS3 class to C/C++. There are two different cases depending whether your run the C/C++ code in the background worker.

Case 1 - C/C++ code in UI worker.

If you invoke your C/C++'s main function using "CModule.start()", or "CModule.startAsync()", or just simply call some C/C++ function using the methods in Part I without executing the C/C++ main function, the C/C++ code will run in the UI worker, the same domain as your main AS3 console class. Then things are easy and there are various ways for passing your Main class's reference, see my examples:
https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/CB_callAS3fromC/nobgcall

Case 2 - C/C++ code in background worker.

If you invoke your C/C++'s main function using "CModule.startBackground()", and want to call some outside AS3 function from your C/C++'s main function, then the thing become a little tricky, because you're not able to share a function reference between workers, i.e., there is no way to pass a function reference from the UI worker - your Main/Console class to the background worker - your C/C++ code, as the class/function reference can't be serialized in AMF3 format. There is one way to circumvent the problem, using MessageChannels:
https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/CB_callAS3fromC/bgcall

In other situations, you can access your Main UI class's properties from the background worker by the "avm2_ui_thunk" and "CModule.serviceUIRequests" combinations, see http://bruce-lab.blogspot.com/2014/07/crossbridge-quake1-example-simplified.html for details.


Links:
http://forums.adobe.com/message/6002640#6002640

http://www.bytearray.org/?p=4423
http://www.bytearray.org/?p=4423#comment-494548

http://help.adobe.com/en_US/as3/dev/WS2f73111e7a180bd0-5856a8af1390d64d08c-8000.html
http://help.adobe.com/en_US/as3/dev/WS2f73111e7a180bd0-5856a8af1390d64d08c-7fff.html
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/system/Worker.html

http://jacksondunstan.com/articles/tag/workers
http://esdot.ca/site/2012/intro-to-as3-workers-hello-world
http://probertson.com/articles/2012/11/07/as3-concurrency-workers-use-cases-best-practices-links/

Tuesday, July 15, 2014

Crossbridge Quake1 Example Simplified

I made some minor modifications of the official Crossbridge Quake1 example so that the source code is easier to use and mod. The original source code uses a very different workflow from the old Alchemy, that is, compile everything, including the C/C++ code, AS code and data file, into the final swf file directly via a single Makefile. Although this approach is elegant and simple as a sample of the Crossbrige SDK, it will cause several inconveniences for a real project. The drawback is obvious, once you changed something, either the C/C++ code, AS code or the data file, you need to recompile everything.

On the other hand, the old Alchemy workflow, that is, compile all the C/C++ code into an independent swc first, then import the swc in the AS project, is more efficient. Although it is possible to use several separated makefiles for different steps of the whole compiling process, the old Alchemy workflow is more friendly to Flash developers.

So what I did in the simplified version is

1. Changed Makefile to compile the swc instead of swf.
The original Makefile mixes gcc and asc, where gcc is used to compile all the C source files into .o files and the final swf file, and asc is used to compile the "Console.as" file. I just removed the part for compiling the "Console.as" file. (The modified "Console.as" file will be used as the Main class for the AS project, in which it will be linked with the swc file later.) Then, changed the option "-emit-swf" for gcc to "-emit-swc" so the swc file, instead of the swf file, will be created.

2. Simplified the way for supplying the file "pak0.pak" to C/C++, so no "genfs" needed.
Crossbrige introduces genfs for the file system. This can be seen as an advantage over Alchemy, but personally, I feel it is not so easy to use. Crossbrige uses the genfs tool to convert all your files/folders needed in your C/C++ code into plain AS text files so the compiler can compile the converted data files into your swf. However, this is a disaster for modding - every time you change the data files, you need to genfs them into AS files first before they can be used in your Corssbrige projects. Fortunately, there is a simple alternative way (the Alchemy-like way, not officially documented, but actually use the same API as the genfs way) for supplying data to C/C++, see this post http://bruce-lab.blogspot.com/2013/11/migrating-from-alchemy-to.html for details. In this way, you handle all the data using AS3 only, so you can embed files using AS3 code, or load them on the run using a URLLoader.

There is one problem, beyond the quake example. That is when you need to supply many files or folders to C/C++. Manually embedding them in pure AS3 is troublesome. In this scenario, it seems the genfs tool will save your the trouble. However, this can also be solved by pure AS3. My solution is zip everything as one package first, then use some AS3 zip library (such as http://nochump.com/blog/archives/15, http://codeazur.com.br/lab/fzip/) to supply all files programmably. (Actually, the quake data file is a zipped package of many files and folders in a custom format ".pak", and the engine itself takes care of all the unzipping, parsing and loading processes.)

3. Created the FlashDevelop project.
Added the swc file generated previously to lib, modified the "Console.as" file, which imports classes/packages needed from the swc file, and embed the game data file in the Main class "Console.as". Besides, an unimplemented preloader class is added in the AS project. The official way for adding preloader directly for Crossbrige generated swf is also not very handy. With an AS project, it's trivial work to implement the preloader.

You can find the source code:
(SVN, source code only) http://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/CrossBridge_Example_Quake1_Simplified/
(All in One Package, everything you need to compile) http://code.flaswf.tk/2014/07/sdlquake1-for-crossbridge-simplified.html

What I learned from the original quake example

The most important files in the example are "Console.as", "sys_sdl.c", "snd_mix.c". The file "sys_sdl.c" is where you can find the C main function, besides, in the file "sys_sdl.c", function
engineTick() is the main game loop, and
engineTickSound() is the main sound loop.

The sdlquake example almost answers most questions when you want to port an SDL based application or game to Flash with Crossbridge.

Q1. How to start the main game loop?
There are two ways showed in the example to run the main game loop in each frame. The first one is to call the C/C++ main loop function engineTick() from AS3 in an EnterFrame event handler, see the line

CModule.callI(enginetickptr, emptyArgs)
in "Console.as". This is single threaded and everything, including both the main game loop and the screen buffer rendering, runs in the main UI worker only.
The second one is to use a background worker, so you can put the main loop function in an infinite while(true) loop in the C main function. In this case, you need two threads, the background worker (all C code) is running the main game loop and does the blitting job while the main UI worker only renders the screen buffer in the EnterFrame event handler. see this post http://bruce-lab.blogspot.com/2014/05/migrating-from-alchemy-to.html for more.

Q2. How to render the ScreenBuffer?
As I explained in http://bruce-lab.blogspot.com/2012/12/migrating-from-alchemy-to-flascc.html, all you need to do is to get pointer to the Screen Buffer(data/array of colour values) of your C/C++ code, see the line
vbuffer = CModule.getPublicSymbol("__avm2_vgl_argb_buffer")
in "Console.as", then create a BitmapData and use the setPixels method to render the buffer.

Q3. How to get the Keyboard input?
Of course you need to listen the KEY_UP and KEY_DOWN events in AS3. Then you can implement the "read" function in "Console.as", so that key inputs can be read by C using normal C IO.

Q4. How to get the Mouse input?
The example showed how to let C know the mouse position. Firstly, mouse position "mx" and "my" can be captured in AS3.
If you're running the main loop in the UI worker (ST), get the pointer of the C variables for storing mouse position:
vgl_mx = CModule.getPublicSymbol("vgl_cur_mx")
vgl_my = CModule.getPublicSymbol("vgl_cur_my")
Then use domain memory to update the values of the two C variables directly in AS3:
CModule.write32(vgl_mx, mx)
CModule.write32(vgl_my, my)

If you're in MT mode, things are a little tricky. The "handleFrame()" in "sys_sdl.c" is for getting mouse input. The function used inline asm to get the values for the mouse positions.
inline_as3(
"import com.adobe.flascc.CModule;\n"
"%0 = CModule.activeConsole.mx\n"
"%1 = CModule.activeConsole.my\n"
: "=r"(vgl_cur_mx),"=r"(vgl_cur_my) :
);
Since you're running the main loop in the background and mouse position can only be retrieved from the UI worker, you need the
avm2_ui_thunk(handleFrame, NULL);
(in C, the main game loop, where you need to update the mouse position, to queue up uiThunk request for calling handleFrame on the UI Worker)
and
CModule.serviceUIRequests()
(in AS3, the EnterFrame handler, to service the pending uiThunk request) combination.

Q5. How to play the sound data?
Use Sound and SoundChannel class in AS3 to play sound data. To get the sound sample data, use inline asm to writeFloat, and the proxy variable "sndDataBuffer" in AS3, see "snd_mix.c" and "Console.as" for details.

Q6. How to supply the files to C?
See the previous section where I talked about the file system.

Some other notes:

1. If you're using 32-bit system with 32-bit java, you need to pass the option -jvmopt="-Xmx1G" to gcc/g++, otherwise, you may get the error "LLVM ERROR: Error: Unable to launch the Java Virtual Machine. This usually means you have a 32bit JVM installed or have set your Java heap size too large. Try lowering the Java heap size by passing "-jvmopt=-Xmx1G" to gcc/g++."

2. On windows, when compiling the original source code, if the compiler complains that "Console.as" is locked and not accessible, try to use some software to unlock the file "Console.as", then compile again.

Special thanks to Michael Guidry (MadGypsy on quakeone.com) for motivating me to write this post.

Thursday, May 1, 2014

Migrating from Alchemy to FlasCC/CrossBridge - The flyield() Method Alternative

In Alchemy, when you're compiling and reusing C/C++ code in Flash, you may encounter the problem caused by loops. In C/C++, it's very common to use a infinity loop such as

while(1)
{
}
or
for(;;)
{
}
where we will put everything such as main game logic, into the loop and break the loop when certain conditions are satisfied. However, this way doesn't work for Flash. At the time of Alchemy, Flash/Action Script 3 was still 'single' threaded. This infinity loop will block everything - no UI updates, no interaction responses, the Flash program looks like dead - as everything else is waiting for the loop to finish. One way to solve the problem is to break this C/C++ run-loop into frame by frame calls on the AS3 side (See CrossBridge SDK's "Sample 4: Animation" for details). At that time, we have one handy function called "flyield()" in the Alchemy C/C++ API, to simplify the solution. All you need is to stuff such function into those infinity loops, and declare the functions contains those infinity loops as "AS3_FunctionAsync". And when Flash sees this "flyield()" function, it will know that it should freeze the loop for a while, jump out to update the UI and let other things work, then come back to run the loop again.

However, there is no such function "flyield()" any more in FlasCC/CrossBridge. But now, we have two ways to deal with such infinity loops. One is the way provided by the newly introduced concurrency API, the other is the classical "flyield()"-like way.

Thanks to the new concurrency API of Action Script 3, you will never need to worry about the error that "Error #1502: A script has executed for longer than the default timeout period of 15 seconds". With workers, you can do all the computation intensive calculations in the background, and let the UI runs in main thread. So those intensive calculations will not block your whole program any more. And the concurrency API is also available in FlasCC/CrossBridge. To use the concurrency API, you can check the "Sample 9 - Pthreads" in the CrossBridge SDK.

In FlasCC/CrossBridge, you simply can run all the C/C++ code in the background worker by the following line in your "Console.as".
CModule.startBackground(this, new [], new [])
The most common case is in your Main loop, you need to pause the logic and let the UI listen to the user input. In many C/C++ applications, the waiting for user input model is an infinity loop. In this case, you can use "avm2_self_msleep" to pause the loop and add an input event listener, once get the user input, use "avm2_wake" to resume the loop and the main logic.
See the following source code of for more details:
https://flaswf.googlecode.com/svn/trunk/Games/Sanguosha/lib
(especially the file "FlasCCPortLayer.cpp". Update: (2014/7/18) Alternative way for getting input is to use the "avm2_ui_thunk" and "CModule.serviceUIRequests" combination, see the Crossbridge quake1 example for details.)

The above way works for some cases, for example when the C/C++ function consume a lot time to run, but is not so convenient for many C/C++ game logic as the old " flyield()" function in the aforementioned case. You need to reorganize the code structure using workers. To make things easy, actually, there is an almost equivalent function in FlasCC/CrossBridge - "avm2_wait_for_ui_frame".
To use this "flyield()" alternative, you must also run your C/C++ code in the background. In other words, you need the following code in your "Console.as" again:
CModule.startBackground(this, new [], new [])
Then, all you need to do is to insert the following code
avm2_wait_for_ui_frame(0);
somewhere in the infinity loop.

One drawback of this method is that you need to put the C/C++ loop in your main function. This is not very convenient as the old "AS3_FunctionAsync" declaration in Alchemy when you want to pass some parameters into the loop. One way is to initialize parameter as global variables in C/C++ by passing values from AS3 side before call the C/C++ main function(CModule.startBackground), another way is to use the C/C++ "argv" - the second parameter of CModule.startBackground. Well, this may solve the problem to pass parameters, another important issue is that how to return values from C/C++ main to AS3? So you can see this workaround, which only works with the C/C++ main function, is still not so convenient as the old asynchronous functions in Alchemy. In this case, different from the main logic loop, actually you usually want a C/C++ function to do some time consuming calculation and return the result, while not be restricted by the Flash script execution time limit. To resolve all the difficulties and troubles fundamentally, you'd better use the more advanced and complicated Pthreads (See "Sample 9: Pthreads") and Workers (run the FlasCC/CrossBridge wrapper function in the background as what you can do with a time consuming AS3 function, see for example http://esdot.ca/site/2012/intro-to-as3-workers-hello-world) with FlasCC/CrossBridge.

Source code of an example using avm2_wait_for_ui_frame:
https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/flyieldAlternative

Links:
http://stackoverflow.com/questions/13560133/increase-flash-script-execution-time-flascc
http://forums.adobe.com/message/6227761

Thursday, January 2, 2014

CrossBridge/FlasCC Resources Collection

Documentation: 

FlasCC Readme
http://www.adobe.com/devnet-docs/flascc/README.html

Release Notes
http://www.adobe.com/go/flascc_releasenotes

Samples
http://www.adobe.com/devnet-docs/flascc/docs/samples.html
 
Reference Guide
http://www.adobe.com/devnet-docs/flascc/docs/Reference.html
 
C/C++ API Reference
http://www.adobe.com/devnet-docs/flascc/docs/capidocs/index.html

ActionScript3 API Reference
http://www.adobe.com/devnet-docs/flascc/docs/apidocs/index.html

Flash Runtime API Reference
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/ 
 

Tutorials:

http://www.adobe.com/devnet/games/articles/compiling-opengl-games.html
http://www.adobe.com/devnet/games/articles/using-cplusplus-code-path-finding.html
http://www.adobe.com/devnet/games/articles/pthreads-flascc.html
http://www.adobe.com/devnet/games/articles/flascc-tips-tricks.html

http://blogs.adobe.com/flascc/
http://blogs.adobe.com/flascc/2012/11/06/using-multiple-flascc-swcs-in-a-flash-project/
http://blogs.adobe.com/flascc/2012/11/09/debugging-multi-threaded-flascc-applications-with-gdb/
http://blogs.adobe.com/flascc/2012/11/17/using-configure-scripts-with-flascc/
http://blogs.adobe.com/flascc/2012/11/30/finding-multi-threading-bugs-with-gdb/
http://blogs.adobe.com/flascc/2012/12/08/operating-on-actionscript-objects-in-c/
http://blogs.adobe.com/flascc/2012/12/14/bringing-opengl-cc-code-to-the-web-with-flascc/
http://blogs.adobe.com/flascc/2012/12/20/troubleshooting-the-could-not-create-the-java-virtual-machine-error/
http://blogs.adobe.com/flascc/2013/01/11/troubleshooting-error-1065/
http://blogs.adobe.com/flascc/2013/01/18/using-printf-within-a-swc/
http://blogs.adobe.com/flascc/2013/01/18/porting-a-c-opengl-game-to-run-in-the-browser/
http://blogs.adobe.com/flascc/2013/03/18/flascc-and-link-time-optimization/

http://www.slideshare.net/PavelNakaznenko/porting-c-apps-to-flascc

http://flascc.blogspot.com/
http://haxestage3d.blogspot.com/2013/01/flascc-on-32-bit-systems.html
http://haxestage3d.blogspot.com/2013/01/flascc.html

Codes:

Some more example ports using flascc to target Flash
https://github.com/alexmac/alcexamples

Ports of various open source libs using FlasCC to target Flash
https://github.com/alexmac/alcextra

Freeglut ported to flash with FlasCC and Stage3D
https://github.com/alexmac/alcfreeglut

https://github.com/adobe/glsl2agal
https://github.com/adobe/GLS3D

Demos:

http://adobe-flash.github.io/crossbridge/
https://github.com/alexmac/AdobeMAX2013
http://blogs.adobe.com/flascc/2013/01/04/sample-c-libraries-running-in-the-browser-via-flash-player/
http://www.cmodule.org/neverball/
http://www.cmodule.org/nehe/
http://www.cmodule.org/

Discussions:

http://forums.adobe.com/community/game_developers/flascc
http://forums.adobe.com/message/5365555#5365555

Others:

CrossBridge SDK Community Releases:
http://sourceforge.net/projects/crossbridge-community/

Sunday, November 3, 2013

Migrating from Alchemy to FlasCC/CrossBridge - Simplify the File System Using CrossBridge's "addFile" as an Alternative to "supplyFile" in Alchemy

Many times, your C/C++ code may rely on external files to work, such as texture files/model files for a 3D engine. One way to supply those file to the CModule in CrossBrige is to use the memory API, which is fast, but need more wrapper codes. Sometimes, use the standard C/C++ I/O API, such as "FILE" and "ifstream", is more convenient for porting existing C/C++ libraries.

CrossBridge needs to process the external files using "genfs" before you can use them. That's why I tried the URLLoaderVFS, a class by twistedjoe from http://forums.adobe.com/thread/1147910. And for different kinds of methods of loading files - Embed, use http/URLLoader and use local shared objects, you need to genfs the external files differently and link with different .as class, which is detailed documented at http://www.adobe.com/devnet-docs/flascc/docs/Reference.html#section_vfs.
However, these are for compilng a swf directly from C/C++ source files. If you compile C/C++ to a swc first, and then compile the swf from your swc and a main.as file, things can be greatly simplified.

I always thought the FlasCC/CrossBridge's file system is more complicated than Alchemy, before I realized that there is a similar way for supplying external files to the C module.

In Alchemy, we only need to use the function "supplyFile(fileName:String, fileData:ByteArray)", and handle the different methods of loading the data file in AS3, use the "Embed" tag, URLLoader or local shared objects.
In CrossBridge, actually we have an alternative function - CModule.vfs.addFile(fileName:String, fileData:ByteArray).
You only need to call the function to supply the data file needed before the line "CModule.startAsync(this);".
And for the data file itself, you can use AS3 code to load. No matter using which ways, treat them as ByteArrays. Once they are loaded or ready, call the function "addFile".

You can check the source code for details:
https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/CrossBridgesupplyFile/

Sunday, October 27, 2013

Simple Chinese Word Segmentation Lib for Flash AS3 - SCWS Ported to Flash Using CrossBridge

Unlike English sentences, in a Chinese sentence, there is no space between two words (http://en.wikipedia.org/wiki/Text_segmentation). This can cause lots of trouble for processing the language on computer.

SCWS is a simple Chinese word segmentation C lib. I just ported it to Flash using CrossBridge - the latest open source version of FlasCC. You can use the pre-build swc library "libscws.swc" in your Flash/AS3 projects.

The SCWS lib depends on an extra ".xdb" dictionary file and a ".ini" rule file, which can be downloaded at http://www.xunsearch.com/scws/download.php. However, the CrossBridge's file system is not as simple as the old Alchemy(See this post, and simplified code), so I use the class by twistedjoe from http://forums.adobe.com/thread/1147910, which doesn't require any genfs processing on the files.

There is almost no modification of the original C source files, except for the file "lock.c", I commented the line to pass the gcc complains:

//#warning no proper flock supported

To use the swc library, you must set compiler options "enable strict mode" to false! Otherwise, the AS3 compiler will throw error "Error: Call to a possibly undefined method addEventListener through a reference with static type CrossBridge.libscws.vfs:URLLoaderVFS".

There are two main functions in the AS3 library: "initialize_SCWS_AS3()" and "scws_send_text_AS3()".
For using the "libscws.swc", firstly, load the dictionary file and the rule file and supply them to the C module. This can be done in common CorssBridge/FlasCC routine: use a URLLoaderVFS's "loadManifest" function to load the manifest file, which contains the files' names and paths.(See the demo's source code for more details, for the manifest file, https://github.com/twistedjoe/flascc-URLLoaderVFS gives more information.) After the dictionary file and the rule file were loaded, call "initialize_SCWS_AS3()", which will initialize the library for use. Then you can call the function "scws_send_text_AS3(input:String):String", with the text to be processed as the parameter, and it will return the processed text, with space as delimiter.

Here is the demo(Input the texts at the bottom, Return Key for sending to the console.):



Full source code of the demo and the lib:
https://flaswf.googlecode.com/svn/trunk/LibSCWS

Links:
http://www.xunsearch.com/scws/
http://nlp.stanford.edu/software/segmenter.shtml
http://ictclas.org/index.html
http://technology.chtsai.org/mmseg/
http://www.coreseek.cn/opensource/
https://github.com/fxsjy/jieba

Sponsors