I'm currently playing around with the wasm build target for rust. I know that wasm-bindgen ist the bridge between rust/wasm and JavaScript. However, I'd like to build a WASM module that is exporting specific functions without using the wasm_bindgen macro as my WASM modules are not intended to be run on the web or in combinition with JS.
What does a function signature need to look like in rust to export it to the wasm module and thus is available to be called from a WASM interpreter ?
You mark your function as #[no_mangle] (don't apply symbol mangling so I can refer to it using the same name) and extern "C" (defines the calling convention).
Here's a Cargo.toml:
# Cargo.toml
[package]
name = "temp"
version = "0.1.0"
authors = ["Michael-F-Bryan <michaelfbryan@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[lib]
crate-type = ["cdylib", "staticlib"]
And my code:
// src/lib.rs
#[no_mangle]
pub extern "C" fn add(left: i32, right: i32) -> i32 {
left + right
}
I then compile it using cargo.
$ cargo build --target wasm32-unknown-unknown --release
Compiling temp v0.1.0 (/tmp/temp)
Finished dev [optimized] target(s) in 0.16s
$ ls target/wasm32-unknown-unknown/release/
build deps examples incremental libtemp.a libtemp.d temp.d temp.wasm
We can convert the temp.wasm to a human-readable form using the tools from WABT.
And you can see there's a func called $add which takes two i32s and returns an i32, and the (export "add" (func $add)) expression says the $add function is publicly accessible.
The wasm-bindgen tool automates a lot of the extern "C" code and sets things up so you can pass more complex types to/from WebAssembly because a function can only use integers and floats as parameters or return values.