Calling C from JS with Emscripten, minimal examples
There are a few ways of doing this, this is the simplest, but also slowest. The options are listed on the Emscripten wiki here.
Return an int, complete example
Sample C file (I called it call.c):
#include <math.h> int test1(int x) { return sqrt(x); } int test2(int x) { return sqrt(x)+1; }
Compile as follows:
emcc call.c -o call.js -s EXPORTED_FUNCTIONS="['_test1','_test2']"
You can then create a html file which calls this JS code:
<!DOCTYPE html> <html> <body> <script src="call.js"></script> <script> var result = Module.ccall( 'test1', // name of C function 'number', // return type ['number'], // argument types [28]); // arguments document.write(result); </script> </body> </html>
Passing and returning an array of ints
This is a little harder, Emscripten doesn’t really help you out, you have to format the arrays in memory manually.
Sample C program two functions, one passing and returning a char *, the other int *s.
#include <math.h> #include <stdlib.h> #include <string.h> char *test1(char *instr) { char *array = malloc(sizeof(char)*strlen(instr)); strcpy(array,instr); // the horror!! int size = strlen(array); for(int n=0;n<size;n++) { if((array[n] >= 'a') && (array[n] <= 'z')) array[n] -= 'a'-'A'; } return array; } int *test2(int *in,int size) { int *array = malloc(sizeof(int)*size); for(int n=0;n<size;n++) { array[n] = in[n]*2; } return array; }
emcc call.c -o call.js -s EXPORTED_FUNCTIONS="['_test1','_test2']"
The JS can then be called from html as follows:
<!DOCTYPE html> <html> <body> <script src="call.js"></script> <script> function write_1d_int32_array(ptr,array) { for(i=0;i<array.length;i++) { Module.setValue(ptr,array[i],'i32'); ptr += 4; } } function read_1d_int32_array(ptr,length) { var array = []; for(i=0;i<length;i++) { var value = Module.getValue(ptr+(i*4),'i32'); array.push(value); } return array; } // test1 - a C function that takes, and returns a C style string (char *) var mystring = "test"; var strptr = Module._malloc(mystring.length); Module.writeAsciiToMemory(mystring, strptr); var retstrptr = Module.ccall('test1', // name of C function 'number', // return type ['number'], // argument types [strptr]); // arguments // Convert the resulting string to a JS string var retstr = Pointer_stringify(retstrptr); document.write(retstr); // test2 - a C function that takes, and returns a C style int array (int *) var myarray = [10,20,30,40,50]; var arrayptr = Module._malloc(myarray.length*4); write_1d_int32_array(arrayptr,myarray); var retarrayptr = Module.ccall('test2', // name of C function 'number', // return type ['number'], // argument types [arrayptr,myarray.length]); // arguments // Convert the resulting pointer to a JS array var retarray = read_1d_int32_array(retarrayptr,myarray.length); document.write(retarray); </script> </body> </html>