DEV Community

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

Posted on

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

Hi Everyone,

In my previous post : Use C/C++ code in DENO using WASM: In VSCODE, using Emscripten, I used Emscripten to convert C/C++ code to WASM and then use it in Deno. Here we will use 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.
  • How: Follow the instructions below.

Prerequisite

  1. VSCODE: IDE
  2. Install WebAssembly plugin in VSCODE:
  3. WASI SDK Download the latest tar.gz file and extract to directory of your choice, we will call it WASI_SDK_HOME.
  4. Deno
  5. C/C++ source code

C++ Example

GIT REPO for all files

Step1: Your C++ Source code.

I have named my C++ code file as app.cpp \
Its a Simple C++ code to create a copy of file based on the run time arguments passed.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <iostream>

int main(int argc, char **argv) {
    ssize_t n, m;
    char buf[BUFSIZ];

    if (argc != 3) {
        fprintf(stderr, "usage: %s <from> <to>\n", argv[0]);
        exit(1);
    }

    int in = open(argv[1], O_RDONLY);
    if (in < 0) {
        fprintf(stderr, "error opening input %s: %s\n", arhttps://github.com/anuragvohraec/EXAMPLE_WASI_CPP_DENOhttps://github.com/anuragvohraec/EXAMPLE_WASI_CPP_DENOgv[1], strerror(errno));
        exit(1);
    }

    int out = open(argv[2], O_WRONLY | O_CREAT, 0660);
    if (out < 0) {
        fprintf(stderr, "error opening output %s: %s\n", argv[2], strerror(errno));
        exit(1);
    }

    while ((n = read(in, buf, BUFSIZ)) > 0) {
        char *ptr = buf;
        while (n > 0) {
            m = write(out, ptr, (size_t)n);
            if (m < 0) {
                fprintf(stderr, "write error: %s\n", strerror(errno));
                exit(1);
            }
            n -= m;
            ptr += m;
        }
    }

    if (n < 0) {
        fprintf(stderr, "read error: %s\n", strerror(errno));
        exit(1);
    }

    std::cout << "Done" << std::endl;

    return EXIT_SUCCESS;
}
Enter fullscreen mode Exit fullscreen mode

Step2: Compile it to wasm using WASI SDK

Lets say you have extracted your WASI SDK tar.gz in ~/wasm-sdk-vers folder we will call it WASI_SDK_HOME in the code below.
You can compile the C++ code to wasm using below command.

`${WASI_SDK_HOME}/bin/clang++ app.cpp --sysroot=${WASI_SDK_HOME}/share/wasi-sysroot -o app.wasm`
Enter fullscreen mode Exit fullscreen mode

This will output app.wasm file.

Step3: Use wasm in deno

Deno file name is test_app.ts

//this standard modoule is required to run wasi code: it provide system calls needed by WASI
import Context from "https://deno.land/std@0.92.0/wasi/snapshot_preview1.ts";

//Create context

const context = new Context({
  args: Deno.args, //args will be the run time argument passed to WASM code
  env: Deno.env.toObject(), //Any environment varibale you wanted to pass
  preopens: {"./":"./"} //Directories which will be hosted in WASI Sandbox to be used by WASM. The string keys of are treated as directories within the sandboxed filesystem, the values are the real paths to those directories on the host machine.
});

const binary = await Deno.readFile("app.wasm");
const module = await WebAssembly.compile(binary);
const instance = await WebAssembly.instantiate(module, {
  "wasi_snapshot_preview1": context.exports,
});

context.start(instance);
Enter fullscreen mode Exit fullscreen mode

Step4: Run the code:

deno --unstable run -A test_app.ts  app.wasm  README.md cr.md
Enter fullscreen mode Exit fullscreen mode

I have readme.md file which I want to copy and create cr.md file.

It should output:

Done
#And create a cr.md file in the directory
Enter fullscreen mode Exit fullscreen mode

Top comments (0)