Introduction to WebAssembly and C++
Modern web development increasingly demands higher performance, especially for tasks such as image processing, 3D graphics, simulations, and cryptography. WebAssembly (WASM) is a low-level binary instruction format that runs in the browser at near-native speed. It allows harnessing the power of C++ in the web environment, opening new horizons for developers.
In this article, we will cover how to compile C++ code to WebAssembly, set up the environment using Emscripten, integrate a WASM module with JavaScript, and optimize performance. You will learn why C++ remains one of the best languages for creating high-performance web applications.
What is WebAssembly and why does a C++ developer need it?
WebAssembly is a virtual machine running in the browser. Unlike JavaScript, WASM is binary code compiled from C, C++, Rust, or other languages. Key advantages:
- Performance — WASM runs 10-50 times faster than JavaScript in computationally intensive tasks.
- Portability — the same code works in Chrome, Firefox, Safari, and Edge without modifications.
- Security — WASM runs in an isolated sandbox, without direct system access.
- C++ Ecosystem — you can reuse existing libraries (OpenCV, TensorFlow Lite, SQLite) on the web.
C++ is ideally suited for WebAssembly due to efficient memory management, the absence of a garbage collector, and a rich set of tools. For example, the Unity engine uses WASM for rendering 3D scenes directly in the browser.
Setting up the environment: Emscripten and compiling C++ to WASM
The primary tool for compiling C++ to WebAssembly is Emscripten. It includes the emcc compiler, which turns C++ code into a .wasm file and a JavaScript wrapper for loading.
Installing Emscripten
# Clone the repositorygit clone https://github.com/emscripten-core/emsdk.gitcd emsdk
# Install the latest version./emsdk install latest./emsdk activate latest
# Add environment variablessource ./emsdk_env.shAfter installation, verify it works with the command emcc --version.
First example: "Hello, WASM!"
Let's create a simple C++ function that adds two numbers:
// hello.cpp#include <emscripten.h>
extern "C" { int EMSCRIPTEN_KEEPALIVE add(int a, int b) { return a + b; }}The key point: the EMSCRIPTEN_KEEPALIVE macro prevents the function from being removed during optimization. Let's compile the code:
emcc hello.cpp -o hello.html -s EXPORTED_FUNCTIONS="['_add']" -s EXPORTED_RUNTIME_METHODS="['ccall', 'cwrap']"The flag -o hello.html creates an HTML file with a usage example. Open it in your browser and call Module.ccall('add', 'number', ['number', 'number'], [5, 3]) — the result will be 8.
Integrating C++ code with JavaScript
After compilation, you get .wasm and .js files. Let's look at how to call C++ functions from JavaScript.
Basic call via ccall/cwrap
// In HTML after loading the script:Module.onRuntimeInitialized = function() { const add = Module.cwrap('add', 'number', ['number', 'number']); console.log('Result:', add(10, 20)); // 30};The cwrap method creates a wrapper for the function that can be called like a regular JS function. Data types: 'number', 'string', 'array'.
Working with memory and arrays
To transfer large amounts of data (e.g., images), use direct memory manipulation: