DEV Community

Cover image for Use C/C++ code in DENO using WASM: In VSCODE, using Emscripten
Anurag Vohra
Anurag Vohra

Posted on

Use C/C++ code in DENO using WASM: In VSCODE, using Emscripten

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

  1. VSCODE: IDE
  2. Install WebAssembly plugin in VSCODE:
  3. EMSCRIPTEN Just follow each steps to install this tool.
  4. Deno
  5. 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;
}
Enter fullscreen mode Exit fullscreen mode

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));
Enter fullscreen mode Exit fullscreen mode

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

GIT for C++ code

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;
}
Enter fullscreen mode Exit fullscreen mode

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.

image

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

image
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));
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

Collapse
 
sant123 profile image
Santiago Aguilar Hernández

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:

#include <emscripten.h>

extern "C" EMSCRIPTEN_KEEPALIVE int add(int x, int y) {
  return x + y;
}

extern "C" EMSCRIPTEN_KEEPALIVE int subtract(int x, int y) {
  return x - y;
}
Enter fullscreen mode Exit fullscreen mode

And since Deno 2.1, you can import wasm modules easier:

import { add, subtract } from "./myLib.wasm";

console.log("add()", add(5, 6));
console.log("subtract()", subtract(10, 7));
Enter fullscreen mode Exit fullscreen mode