Skip to content

Interacting with code

kripken edited this page Feb 23, 2012 · 54 revisions

Interacting with Compiled Code

Direct Interaction

You can directly interact in various ways with the compiled code:

  • ccall lets you call a compiled C function from JS. It will do type translations for you. For example, ccall('my_function', 'number', ['number', 'string'], [5, "hello"]) will call a function called my_function, which returns a number (and int or a float), and receives two parameters, a number and a string; in this example we send the function 5 and "hello".
    • See the definition of ccall in src/preamble.js for the latest documentation. There is also cwrap which returns a JS function that you can call normally, which makes it simpler than ccall if you repeatedly call the same function more than once.
  • Functions in the original source become JS functions, so you can call them directly if you do type translations yourself - this will be faster than using ccall, but a little more complex.
    • The types of the parameters you pass to functions need to make sense. Integers and floating point values can be passed as is. Aside from those, there are pointers, which are simply integers in the generated code.
    • Strings in JavaScript must be converted to pointers for compiled code, the relevant functions are Pointer_stringify which given a pointer returns a JavaScript string, and the other direction can be accomplished by allocate(intArrayFromString(someString), 'i8', ALLOC_STACK) which will convert a JavaScript string someString to a pointer. Note that conversion to a pointer allocates memory (that's the call to allocate there).
  • You can access memory using getValue(ptr, type) and setValue(ptr, value, type). The first argument is a pointer, a number representing a memory address. type must be an LLVM IR type, one of i8,i16,i32,i64,float,double or a pointer type like i8*.
  • There are various other convenience functions, see preamble.js (that file will be included with the generated code).
  • The bindings generator can generate convenient JS classes from C++ headers. See the bindings test in the test runner, and the ammo.js project (the main consumer of that tool)
  • For filesystem-related manners, see the Filesystem Guide.

Affecting Execution

You can affect how code runs by creating an object called Module before the compiled script. Certain properties on Module can then have various effects:

  • arguments: The commandline arguments (if the compiled code checks argc, argc, it will be seeing arguments)
  • print: Called when something is printed to standard output.
  • preRun: A function to call right before calling run, but after defining and setting up the environment. This is useful, for example, to set up directories and files using the FileSystem API (since that needs the FileSystem API to be defined, but also needs to be done before the program starts to run).
  • noInitialRun: If set to true, run will not be called (so memory will not be initialized and the compiled code's main is not executed), and you should call it yourself later.

For example,

var Module = {
  'print': function(text) { alert(text) }
};

This will cause all printouts from the program to be calls to alert.

Important: If you run closure compiler on your code (which is done by default in -O2 and above), you will need quotation marks around the properties of Module as in the example above (and you need to run closure on the compiled code together with the declaration of Module).