Building ofLive: Interacting between JavaScript and C code

I recently released ofLive, a tool embedding the Emscripten version of OpenFrameworks and binding it to an HTML5 code editor (in this case ACE).

One of the main challenge I encountered when building the application was how to communicate between Emscripten generated code and regular JavaScript. In this post, I will briefly explain how to create an Emscripten library that allow that.

I also created a small website using PHP/MySQL, see the source in the ofLive repository.

Building a library, the basics

To build a JavaScript library for Emscripten, I first started with a base template:

Base javascript library

JavaScript

1

2

3

4

5

6

7

8

9

10

11

varLibraryOfLive={

$OFLIVE:{

},

editor_init:function()

{

},

}

autoAddDeps(LibraryOfLive,'$OFLIVE');

mergeInto(LibraryManager.library,LibraryOfLive);

The $OFLIVE array is where you put all the content you need to access outside of Emscripten, you can put for example function pointers that will allow you to call C code directly from JavaScript. The editor_init function will be registered by Emscripten at compilation time, so you can call it from c to invoke JavaScript code. It’s important to note that this function must have a corresponding declaration in the C code. Here’s the header corresponding to this library :

C header

C

1

2

3

4

5

6

#pragma once

extern"C"{

//functions calling javascript library from c

externvoideditor_init();

}

The function signature in C must reflect the function signature in JavaScript. Now let’s add another function to our library, this time we will add a C function that we can call from JavaScript. Here’s the edited library code:

Here, we basically use Module.cwrap to search for a C function named ‘backend_loadlua’, the other parameters allow us to specify the return type (number in this case) and the list of parameters the C function has (here a single string parameter). We also set our backend_loadlua JS function pointer in the $OFLIVE array with the result returned by Module.cwrap, so that we can call this function in JavaScript this way

C function call from JavaScript

JavaScript

1

OFLIVE.backend_loadlua('here lua code')

At last, we must obviously implement this function in our native code, here’s the updated header:

updated header

C

1

2

3

4

5

6

7

8

9

#pragma once

extern"C"{

//functions calling javascript library from c

externvoideditor_init();

//functions calling c code from javascript

intbackend_loadlua(constchar*scriptcontent_from_js);

}

then the definition of the function:

function definition

C

1

2

3

4

5

intbackend_loadlua(constchar*scriptcontent_from_js)

{

std::stringscript_content(scriptcontent_from_js);

ofLogError()<<script_content;

}

That’s it for the code part, now we need to tell the Emscripten compiler about our library and our C functions that we want to export. Use the flag “–js-library” followed by the path to your JavaScript library to embed it in the final Emscripten app. Then use the flag “-s EXPORTED_FUNCTIONS” to specify the list of C functions to export to JavaScript.

Don’t forget to add an underscore in front of your function name and also to specify the main function as Emscripten doesn’t add it automatically (If you forget to include it, your app won’t start since it can’t access the main function)

Small precision: you can use in your library code things like jQuery but ONLY inside a function. Also, the editor_* function are NOT available from JavaScript, only function that you want to call from C must be defined here.