Hi Everyone,
If you have faced issues like me in finding concise tutorial on how to run C/C++ code in Deno using WASM, this is a to the point tutorial for you.
Prerequisites
- VSCODE: IDE
- Install WebAssembly plugin in VSCODE:
- EMSCRIPTEN Just follow each steps to install this tool.
- Deno
- C/C++ source code.
C Example
Step1: C Source code
We will use fairly simple code to demonstrate the concept.
We have a add.c
file which exposes a single function add
from it using emscriten macros.
#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE
int add(int x, int y) {
return x + y;
}
Consider this as a facade for your C library.
Macro EMSCRIPTEN_KEEPALIVE from
emscripten.h
is required for all function you want to expose to be used in your Deno code.
Step2: Create WASM file
Run emscripten emcc
tool on your C file.
${EMSDK_HOME}/upstream/emscripten/emcc add.c -O3 --no-entry -o add.wasm
Explanation for the above command:
- -O3 WIll Optimize your WASM to best possible way. Used for production release.
- --no-entry flag is required as our code has no main function.
- -o will create an output file.
This will create a add.wasm
file.
Step3: Use WASM in DENO
I created a file usewasm.ts
:
//loads wasm file
export const f = await Deno.open("./add.wasm")
const buf = await Deno.readAll(f);
//load it as module
const wasmModule = new WebAssembly.Module(buf);
const wasmInstance = new WebAssembly.Instance(wasmModule);
//export the C functions in DENO!
const add = wasmInstance.exports.add as CallableFunction;
const subtract = wasmInstance.exports.subtract as CallableFunction;
//Use C functions
console.log(add(4,2));
Step4: Run the Deno code
deno run --allow-read usewasm.ts
- --allow-read : as our code will read wasm file
It should out put 6
.
C++ Example
Step1: C++ Source code
We will use fairly simple code to demonstrate the concept.
We have a mylib.cpp
file which exposes a two functions add
and subtract
from it using emscriten macros.
#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE
int add(int x, int y) {
return x + y;
}
EMSCRIPTEN_KEEPALIVE
int subtract(int x, int y){
return x-y;
}
Consider this as a facade for your C++ library.
Macro EMSCRIPTEN_KEEPALIVE from
emscripten.h
is required for all function you want to expose to be used in your Deno code.
Step2: Create WASM file
Run emscripten emcc
tool on your C++ file.
${EMSDK_HOME}/upstream/emscripten/emcc mylib.c++ -O3 --no-entry -o mylib.wasm
Explanation for the above command:
- -O3 WIll Optimize your WASM to best possible way. Used for production release.
- --no-entry flag is required as our code has no main function.
- -o will create an output file.
This will create a mylib.wasm
file.
Step3: View generated wasm file.
If you have install the webassembly plugin mentioned in the pre-requisite, then you should see semthing like this after clicking Do you want to open it anyway?
.
Pay attention to _Z3addii
and _Z8subtractii
, this will be the name of the functions exported by your wasm. (Strange but in C++, unlike in C this exta prefix and suffix are added to your function name).
Step4: Use WASM in DENO
I created a file usewasm.ts
:
//loads wasm file
export const f = await Deno.open("./mylib.wasm");
const buf = await Deno.readAll(f);
//load it as module
const wasmModule = new WebAssembly.Module(buf);
const wasmInstance = new WebAssembly.Instance(wasmModule);
//export the C++ functions in DENO!: The function name can be seen in WASM file using VSCODE plugin
const add = wasmInstance.exports._Z3addii as CallableFunction;
const subtract = wasmInstance.exports._Z8subtractii as CallableFunction;
CallableFunction;
//Use C functions
console.log(add(4,2));
console.log(subtract(6,2));
Step5: Run the Deno code
deno run --allow-read usewasm.ts
- --allow-read : as our code will read wasm file
It should out put:
6
4
...
I have another reference sheet using WASI, instead of EMSCRIPTEN:
Use C/C++ code in DENO using WASM: In VSCODE, using WASI SDK
About WASI
What: WASI: Web assembly system interface.
Why: If your C/C++ code needs to make system call (say File IO, Socket, Clocks, Random numbers). Than you need WASI.
Top comments (1)
Awesome example, thank you so much. About the strange naming in the functions is because C++ mangles them to support function overloading. However you can get rid of this using
extern "C"
. The code will look like this:And since Deno 2.1, you can import wasm modules easier: