Coder Social home page Coder Social logo

rich-murphey / wasm-hostcall-example Goto Github PK

View Code? Open in Web Editor NEW
11.0 1.0 5.0 114 KB

This is an example showing how to export and import functions between a Rust application and Rust WebAssembly.

License: MIT License

Makefile 3.42% Rust 96.58%
rust webassembly webassembly-demo wasmtime hostcall wasm wasm-bindgen

wasm-hostcall-example's Introduction

Contents

WebAssembly passing Structs to Host functions

This demo shows WebAssembly (Wasm) calling host application functions, where both Wasm and application are in Rust. In particular, Wasm is passing references to objects that have either static or dynamic size.

Wasmtime is an embedded WebAssembly virtual machine runtime. The Rust application uses Wasmtime to load and run a Rust WebAssembly module. This demo shows the WebAssembly module calling functions in the host application.

Wasmtime is new and evolving. Features to import and export functions between WebAssembly and host will almost certainly be enhanced. Here are some production uses:

  • Fastly provides a http_guest API. Customers use this to deploy Rust web apps on edge compute.
  • Cloudflare provides a Wasm Wireshark firewall API, Wirefilter, to run customer Wasm firewall at the edge. Cloudflare is expanding this to Web Application Firewall.

This demo is intended to show how to work within certain interim limitations on argument types.

One limitation is, WebAssembly (Wasm) is 32-bit while the application is 64-bit. Wasm pointers are a 32-bit offset in Virtual Machine (VM) memory. To obtain a 64-bit address on the host side, Wasm pointers must be indexed into VM memory's byte array. Fat pointers such as &[u8] or &str are handled transparently on the WebAssembly side; however, on the host side, they are received as two separate arguments, the 32-bit offset and size.

An additional limitation is pointers to structs. Passing a pointer to a struct (e.g. &struct) requires additional code in both WebAssembly and the host application. This demo shows examples for two kinds of structs:

  • Structs that have the Serialize trait. We serialize it and pass the offset and length of the serialized copy instead. Fields can be String, Vec and other dynamic sized types.
  • Structs that have the Copy trait โ€” a fixed size and no pointer fields. We pass the the offset and size of the struct itself.

There are certain trade-offs.

  • Serialization verifies the struct's field types.
  • Directly passing 'Copy' structs does not, and is faster.

In both examples here, the size of the struct is verified.

Prerequisites

To build this demo, first install rust, then add features:

rustup target add wasm32-wasi
cargo install wasm-pack

Building

After the above, clone this project:

git clone https://github.com/rich-murphey/wasm-hostcall-example.git
cd wasm-hostcall-example

Then build the WebAssembly module:

wasm-pack build wasm

Then build and run the application:

cargo run

Code Samples

Rust WebAssembly imports these functions from the host application to demonstrate passing various argument types:

fn log_int(s: i32)   // passes an integer
fn log_str(s: &str)  // passes pointer and size, zero-copy.
fn log_ab(ab: &AB)   // passes pointer and size of a serialized copy
fn log_cd(cd: &CD)   // passes pointer and size of a struct, zero-copy.

#[derive(Debug, Serialize, Deserialize)]
pub struct AB {
    pub a: u32,
    pub b: String,
}

#[derive(Debug, Copy, Clone)]
pub struct CD {
    pub c: i32,
    pub d: ArrayString::<[u8; CD_N]>,
}

The WebAssembly (Wasm) function hello() in wasm/src/lib.rs calls the above functions.

pub fn hello() -> Result<i32,JsValue> {
    log_int(1234);
    log_str("Hello World!");
    log_ab(&AB{a: 1234, b: "abcd".to_string()});
    log_cd(&CD::from(1234, "hello world"));
    Ok(4567)
}

The WebAssembly side of the API is defined in wasm/src/imports.rs. Note that log_int() and log_str() do not need any additional conversion on the WebAssembly side.

The host (application) side of the API is defined in src/exports.rs:

// Given a rust &str at an offset and size in caller's Wasm memory, log it to stdout.
fn log_str(caller: Caller<'_>, offset: i32, size: i32) -> Result<(), Trap> {
    let mem :Memory = mem_from(&caller)?;                 // caller's VM memory
    let slice :&[u8] = slice_from(&mem, offset, size)?; // string's byte slice
    let string :&str = std::str::from_utf8(slice)         // convert to utf-8
        .or_else(|_|Err(Trap::new("invalid utf-8")))?;
    println!("str: {}", string);                          // print the string
    Ok(())
}

See exports.rs and imports.rs for the corresponding code for the other functions in the API.

Acknowledgments

Suggestions and comments are welcome. Please feel free to open an issue if you can suggest improvements, or find parts that are unclear.

wasm-hostcall-example's People

Contributors

rich-murphey avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.