Export functions from WASM library w/o using wasm_bindgen

Hi there,

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 ?

Thanks in advance for any guidance.

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


crate-type = ["cdylib", "staticlib"]

And my code:

// src/lib.rs

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.

$ wasm2wat target/wasm32-unknown-unknown/release/temp.wasm
  (type (;0;) (func (param i32 i32) (result i32)))
  (func $add (type 0) (param i32 i32) (result i32)
    local.get 1
    local.get 0
  (table (;0;) 1 1 funcref)
  (memory (;0;) 16)
  (global (;0;) (mut i32) (i32.const 1048576))
  (global (;1;) i32 (i32.const 1048576))
  (global (;2;) i32 (i32.const 1048576))
  (export "memory" (memory 0))
  (export "add" (func $add))
  (export "__data_end" (global 1))
  (export "__heap_base" (global 2)))

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.