Skip to content

React + Cpp + WebAssembly Todo Application to learn about WebAssembly. This repo can serve as a good starter example on how to build a C++ and React with WebAssembly.

Notifications You must be signed in to change notification settings

daxter-army/react-cpp-wasm-app

Repository files navigation

React + Cpp + WebAssembly (WASM) Todo App

app-ui

💡 Idea

  • 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.

🚀 Prerequisites

  • 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)

🚇 Development

👔 C++ Logic Implementation

  • note.cpp: Contains implementation regarding an individual Note, 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 of vector<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. The Notes class contains the CRUD functionality for altering todos at its side.

  • main.cpp: Contains main() driver code for Notes class, which is not doing much, but acting as an entry point.

🏋️ C++ & WASM Bundling using Emscripten

  • 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']"
    1. -lembind: Directs to use EMSCRIPTEN_BINDINGS
    2. -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.
    3. -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.
    4. "EXPORTED_RUNTIME_METHODS=['ccall']": The method that we use to call C++ code, other method is cwrap().

🦺 WASM Integration with React App

  • A Module object is attached to the window object, and therefore we can refer to our wasm module at window.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 in instance variable.
  • We can call Notes -> add("Learn WASM!") like this instance.add("Learn WASM!") here and so on.
  • Further NotesContext and WASMContext are used in the React App to handle and distribute data among the whole app.

⛓️ Local Development Setup

🛠️ Development Workflow I followed

  1. Write C++ code ⤵
  2. Bundle the code with Emscripten
  3. Copy the 2 output files /cpp_files/<file_name>.js, /cpp_files/<file_name>.wasm to /wasm
  4. 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.

🚦 Directory Notes

  • 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 with emcc 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 at http://localhost:5173.
  • hit npm run build to create production build of React app.

🍀 Resources

About

React + Cpp + WebAssembly Todo Application to learn about WebAssembly. This repo can serve as a good starter example on how to build a C++ and React with WebAssembly.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published