Export WebAssembly Functions to JavaScript
To run high-performance WebAssembly (Wasm) code in a web application,
you must export functions from your compiled binary so JavaScript can
access them. This article explains how to mark functions for export in
languages like C/C++ and Rust, compile them into a .wasm
module, and load and call those functions directly within your
JavaScript runtime.
Step 1: Export the Function in Your Source Language
Before compiling your code to WebAssembly, you must explicitly declare which functions should be exposed to the outside environment.
In C/C++ (using Emscripten)
Use the EMSCRIPTEN_KEEPALIVE attribute. This prevents
the compiler from optimizing the function away and automatically adds it
to the exported functions list.
#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE
int add(int a, int b) {
return a + b;
}In Rust
Use the #[no_mangle] attribute and the
pub extern "C" signature to ensure the function name
remains readable and uses the standard C calling convention.
#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
a + b
}In WebAssembly Text Format (WAT)
If writing raw WebAssembly Text, use the export keyword
inside your module definition.
(module
(func $add (param $a i32) (param $b i32) (result i32)
local.get $a
local.get $b
i32.add)
(export "add" (func $add))
)
Step 2: Load and Call the Function in JavaScript
Once you compile your source code into a .wasm file, you
must load, compile, and instantiate it in JavaScript. The exported
functions are exposed on the instance.exports object of the
instantiated WebAssembly module.
Using async/await (Recommended)
The most efficient way to load WebAssembly in the browser is via
WebAssembly.instantiateStreaming, which compiles the module
while it is still downloading.
async function initWasm() {
try {
// Fetch and compile the WebAssembly binary
const { instance } = await WebAssembly.instantiateStreaming(
fetch('module.wasm')
);
// Access the exported "add" function
const addResult = instance.exports.add(15, 30);
console.log(`Result from Wasm: ${addResult}`); // Outputs: Result from Wasm: 45
} catch (error) {
console.error("Failed to load WebAssembly module:", error);
}
}
initWasm();Fallback for Older Browsers or Node.js
If instantiateStreaming is not supported (for example,
in older Node.js environments), you can read the binary into an
ArrayBuffer first and then compile it:
const fs = require('fs');
async function initNodeWasm() {
const wasmBuffer = fs.readFileSync('module.wasm');
const { instance } = await WebAssembly.instantiate(wasmBuffer);
const result = instance.exports.add(10, 20);
console.log(result); // Outputs: 30
}
initNodeWasm();