Linking Modules - Wasmtime

## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# Linking modules

You can also browse this source code online and clone the wasmtime repository to run the example locally.

This example shows off how to compile and instantiate modules which link together. Be sure to read the API documentation for `Linker` as well.

## `linking1.wat`

    (module
      (import "linking2" "double" (func $double (param i32) (result i32)))
      (import "linking2" "log" (func $log (param i32 i32)))
      (import "linking2" "memory" (memory 1))
      (import "linking2" "memory_offset" (global $offset i32))

      (func (export "run")
        ;; Call into the other module to double our number, and we could print it
        ;; here but for now we just drop it
        i32.const 2
        call $double
        drop

        ;; Our `data` segment initialized our imported memory, so let's print the
        ;; string there now.
        global.get $offset
        i32.const 14
        call $log
      )

      (data (global.get $offset) "Hello, world!\n")
    )

## `linking2.wat`

    (module
      (type $fd_write_ty (func (param i32 i32 i32 i32) (result i32)))
      (import "wasi_snapshot_preview1" "fd_write" (func $fd_write (type $fd_write_ty)))

      (func (export "double") (param i32) (result i32)
        local.get 0
        i32.const 2
        i32.mul
      )

      (func (export "log") (param i32 i32)
        ;; store the pointer in the first iovec field
        i32.const 4
        local.get 0
        i32.store

        ;; store the length in the first iovec field
        i32.const 4
        local.get 1
        i32.store offset=4

        ;; call the `fd_write` import
        i32.const 1     ;; stdout fd
        i32.const 4     ;; iovs start
        i32.const 1     ;; number of iovs
        i32.const 0     ;; where to write nwritten bytes
        call $fd_write
        drop
      )

      (memory (export "memory") 2)
      (global (export "memory_offset") i32 (i32.const 65536))
    )

## `linking.rs`

    //! Example of instantiating two modules which link to each other.

    // You can execute this example with `cargo run --example linking`

    use wasmtime::*;
    use wasmtime_wasi::WasiCtx;

    fn main() -> Result<()> {
        let engine = Engine::default();

        // First set up our linker which is going to be linking modules together. We
        // want our linker to have wasi available, so we set that up here as well.
        let mut linker = Linker::new(&engine);
        wasmtime_wasi::preview1::add_to_linker_sync(&mut linker, |s| s)?;

        // Load and compile our two modules
        let linking1 = Module::from_file(&engine, "examples/linking1.wat")?;
        let linking2 = Module::from_file(&engine, "examples/linking2.wat")?;

        // Configure WASI and insert it into a `Store`
        let wasi = WasiCtx::builder().inherit_stdio().inherit_args().build_p1();
        let mut store = Store::new(&engine, wasi);

        // Instantiate our first module which only uses WASI, then register that
        // instance with the linker since the next linking will use it.
        let linking2 = linker.instantiate(&mut store, &linking2)?;
        linker.instance(&mut store, "linking2", linking2)?;

        // And with that we can perform the final link and the execute the module.
        let linking1 = linker.instantiate(&mut store, &linking1)?;
        let run = linking1.get_typed_func::<(), ()>(&mut store, "run")?;
        run.call(&mut store, ())?;
        Ok(())
    }