Thursday, March 24, 2011

Alchemy Series Part 5: Revenge of the Thiz

Alchemy Series Part 5: Revenge of the Thiz:

This episode is a bit of a catch all for some other random things that we wanted to cover in this series. The hope is, by the time you are done reading this post (along with the last 4) you will be able to start build swcs of other libraries, or even creating your own directly in C. If this ends up being the case, please let us know, we would love to see what you guys make! Anywho, on with the show…

For any of this to make sense, you will probably want to follow along with the code in the example which you can download here:
Example Source

Multiple File Compilation and Linking
While doing my own research on Alchemy, I came across many a forum post asking about compiling and linking C libraries that were comprised of multiple files, as most are. So this week’s example has been split up into multiple files to try and demonstrate the process. In the alchemy folder bundled with the example code, this is a folder called “lib”. In there is a couple of C files and a few Bash scripts. For the purpose of this example, we are going to consider this our Library. In order get our library compiled and ready to link with our Alchemy wrapper we have to complete a few intermediate steps.

The first step is to compile each of the .c files individually and create .o (object) files from them. These object files are what is linked together in the end to create the swc. Since most C libraries out there have lots of files, its probabaly most convenient to create a bash script to handle the compile. In our case its the “compilelib.sh” file.

#!/bin/bash
optLevel=3
 
gcc -I../include -I./ -Wall -O$optLevel -c loopstart.c
gcc -I../include -I./ -Wall -O$optLevel -c cancelstate.c

The first line should look familiar to you from previous posts, but just in case you missed it, it simply tells cygwin to interpret this script with the “bash” shell located at “/bin/bash”. Next we create a variable to make it easy to alter some compile settings without having to edit each line individually. Then we have the now familiar “gcc” calls. The “-I” switches tell gcc to add these folders to its search path when looking for files and definitions, such as (.h) header files. In this case we are telling it to look in the “include” folder one level up, and to also look in its own folder. The “include” folder has our “alcexample.h” file which contains the declarations for our library functions and data structures. The -Wall tells gcc to report all types of warnings while compiling. -O is the compiler optimization setting. At one point I thought the optimization was messing with Alchemy, I was wrong. But I figured it would be good to suggest leaving the variable in there as an example. You could probably do the whole include bit with a var too. Lastly “-c” tells gcc to not run the linker, and just save out the object file. Once those files have been compiled into object files, we need to archive the library together into one file. Thus the “arclib.sh” script:

#!/bin/bash
ar csr exampleLib.a loopstart.o cancelstate.o

To build the archive we use the “ar” program. The command line settings break down like this:
c – create the archive
s – this creates an object file index in the archive which “allows routines in the library to call each other without regard to their placement in the archive” (from ranlib docs)
r – inserts the object file into the archive and replaces duplicates instead of appending

Lastly we feed it the name we want the archive to be called and a list of object files we want included.

At this point we have the library built and archived ready for use in our Alchemy wrapper. So if you pop up one folder level you will see our main Alchemy file, alcexample.c, as well as another Bash script that will finish our build called “compileandlink.sh”:

#!/bin/bash
gcc -I./include -L./lib -lexampleLib -Wall alcexample.c -swc -O3 -o alcexample.swc

This looks very similar to our “compilelib.sh” script, with a couple of notable exceptions. This time we are using the “-L” switch to add a library path to the gcc search path. We then follow that with a “-l” switch and the name of our library. The “-c” has also been replaced by a “-o” and a “-swc”. Which means that gcc will now link the project and create your brand new .swc file :)

So, basically the moral of the story is to build a multi-file library, it takes three steps:
1) Basic library compile to object files
2) Archiving of the .o files to a single archive file (with indicies)
3) Final compile and link

Great, now that we can compile the example, lets jump back into looking at code.

Bound States
So a few posts ago, I had mentioned that the first parameter for the AS3_Function() call was usually NULL, and I at the time didn’t know why. Well, its been figured out :) You can replace this NULL with a pointer to some data of whatever kind you like. This can be a handy shortcut so you don’t have to continuously pass in the pointer address from flash to your function calls when you want to access data within the C code. If you take a look at the alcexample.c file and head down to main(), you will see it looks much like the rest of the examples. However instead of passing NULL into our AS3_Functions we are now passing a pointer to a struct[...]

No comments:

Post a Comment