- So as we all know WebAssembly or WASM is a new type of code that can be run in modern web browsers. We can use Low-Level languages like C/C++, Go, Rust etc, to compile them in binary format, that can be run alongwith JS in the browser. So I was also very much excited with the idea, so here is an implementation from my side, which implements a simple Todo App, using C++ at the back handling all the logic for CRUD regarding managing Todos, and at the front React is being used to communicate with C++ code (Classes and Objects) and displaying UI. App idea is not something new, it is simple, but I wanted to learn how this technology works, as this was my first WebAssembly app/playground.
- NodeJS > 16.x (By default, Emscripten uses its own version of NodeJS, but you can change this if you want to, I proceeded with the default version which is downloaded with emscripten. Visit docs to learn more)
- C++ >= 11 (gcc/g++ version)
- Emscripten (The tool which converts C++ code to wasm code) (Whichever is the latest stable version)
note.cpp
: Contains implementation regarding an individualNote
, which hosts to private member variables the following attributes:
attribute | type | description |
---|---|---|
description | string | string which describes the todo |
status | bool | status whether it is completed or not |
-
Contains public member functions to implement basic utility functionalities.
-
notes.cpp
: Contains implementation ofvector<Note*> notes
, which acts as an array to hold todos in it. Just like the way we put todos in an array in JS, and then manipulate it. TheNotes
class contains the CRUD functionality for altering todos at its side. -
main.cpp
: Containsmain()
driver code for Notes class, which is not doing much, but acting as an entry point.
- Our main aim is to call the public member functions defined in
Notes
class from our JS code. - EMSCRIPTEN_BINDINGS is used to bind C++ classes, so that they are available to call from JS. You can choose what function to expose or not, and it will also affect your bundle size. More functions will result in increased bundle size.
#define EXTERN extern "C"
is used to avoid Name Mangling.- Build Command:
emcc -lembind -o wasm.js main.cpp -s NO_EXIT_RUNTIME=1 -s "EXPORTED_RUNTIME_METHODS=['ccall']"
-lembind
: Directs to use EMSCRIPTEN_BINDINGS-o <name_of_js_glue_code_file.js> <name_of_cpp_code_file.cpp>
: Names for the files to be generated by emscripten. No need to put name of all C++ files. They are automatically handled, just put the name os entrypoint file for C++ code.-s NO_EXIT_RUNTIME=1
: Tells the C++ code to not exit, as we can call its functions anytime. Otherwise the code would exit and we would get errors."EXPORTED_RUNTIME_METHODS=['ccall']"
: The method that we use to call C++ code, other method iscwrap()
.
- A Module object is attached to the
window
object, and therefore we can refer to our wasm module atwindow.Module
- We can initialise our class's instance like this
var instance = new windowm.Module.Notes()
. - Above line will initialize an object of type
Notes
, which is saved ininstance
variable. - We can call
Notes -> add("Learn WASM!")
like thisinstance.add("Learn WASM!")
here and so on. - Further
NotesContext
andWASMContext
are used in the React App to handle and distribute data among the whole app.
- Write C++ code ⤵
- Bundle the code with Emscripten ⤵
- Copy the 2 output files
/cpp_files/<file_name>.js
,/cpp_files/<file_name>.wasm
to/wasm
⤵ - Adjust the imports in
index.html
(If you have changed file names)
- First you can develop C++ code and check that, everyting is working fine with your C++ code, then you can go for building the code with Emscripten.
- All C++ related code is in
cpp_files
. When done, can use Emscripten to bundle these files. - You can use compression flags like
-O0
,-O1
,-O2
,-O3
withemcc
command to compress and minify your wasm and JS glue files. - Parent Directory houses the React client code.
- Open terminal at the parent Directory and hit
npm run dev
and your code is live athttp://localhost:5173
. - hit
npm run build
to create production build of React app.