Files
wasmer/examples/exports_global.rs
2023-03-16 05:59:47 -07:00

141 lines
4.3 KiB
Rust

//! A Wasm module can export entities, like functions, memories,
//! globals and tables.
//!
//! This example illustrates how to use exported globals. They come
//! in 2 flavors:
//!
//! 1. Immutable globals (const),
//! 2. Mutable globals.
//!
//! You can run the example directly by executing in Wasmer root:
//!
//! ```shell
//! cargo run --example exported-global --release --features "cranelift"
//! ```
//!
//! Ready?
use wasmer::{imports, wat2wasm, Instance, Module, Mutability, Store, Type, TypedFunction, Value};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Let's declare the Wasm module with the text representation.
let wasm_bytes = wat2wasm(
br#"
(module
(global $one (export "one") f32 (f32.const 1))
(global $some (export "some") (mut f32) (f32.const 0))
(func (export "get_one") (result f32) (global.get $one))
(func (export "get_some") (result f32) (global.get $some))
(func (export "set_some") (param f32) (global.set $some (local.get 0))))
"#,
)?;
// Create a Store.
let mut store = Store::default();
println!("Compiling module...");
// Let's compile the Wasm module.
let module = Module::new(&store, wasm_bytes)?;
// Create an empty import object.
let import_object = imports! {};
println!("Instantiating module...");
// Let's instantiate the Wasm module.
let instance = Instance::new(&mut store, &module, &import_object)?;
// Here we go.
//
// The Wasm module exports some globals. Let's get them.
// Note that
//
// ```
// get_global(name)
// ```
//
// is just an alias to
//
// ```
// get::<Global>(name)`.
// ```
let one = instance.exports.get_global("one")?;
let some = instance.exports.get_global("some")?;
println!("Getting globals types information...");
// Let's get the globals types. The results are `GlobalType`s.
let one_type = one.ty(&store);
let some_type = some.ty(&store);
println!("`one` type: {:?} {:?}", one_type.mutability, one_type.ty);
assert_eq!(one_type.mutability, Mutability::Const);
assert_eq!(one_type.ty, Type::F32);
println!("`some` type: {:?} {:?}", some_type.mutability, some_type.ty);
assert_eq!(some_type.mutability, Mutability::Var);
assert_eq!(some_type.ty, Type::F32);
println!("Getting global values...");
// Getting the values of globals can be done in two ways:
// 1. Through an exported function,
// 2. Using the Global API directly.
//
// We will use an exported function for the `one` global
// and the Global API for `some`.
let get_one: TypedFunction<(), f32> = instance
.exports
.get_function("get_one")?
.typed(&mut store)?;
let one_value = get_one.call(&mut store)?;
let some_value = some.get(&mut store);
println!("`one` value: {:?}", one_value);
assert_eq!(one_value, 1.0);
println!("`some` value: {:?}", some_value);
assert_eq!(some_value, Value::F32(0.0));
println!("Setting global values...");
// Trying to set the value of a immutable global (`const`)
// will result in a `RuntimeError`.
let result = one.set(&mut store, Value::F32(42.0));
// The global is immutable
assert!(result.is_err());
// assert_eq!(
// result.expect_err("Expected an error").message(),
// "Attempted to set an immutable global"
// );
let one_result = one.get(&mut store);
println!("`one` value after `set`: {:?}", one_result);
assert_eq!(one_result, Value::F32(1.0));
// Setting the values of globals can be done in two ways:
// 1. Through an exported function,
// 2. Using the Global API directly.
//
// We will use both for the `some` global.
let set_some: TypedFunction<f32, ()> = instance
.exports
.get_function("set_some")?
.typed(&mut store)?;
set_some.call(&mut store, 21.0)?;
let some_result = some.get(&mut store);
println!("`some` value after `set_some`: {:?}", some_result);
assert_eq!(some_result, Value::F32(21.0));
some.set(&mut store, Value::F32(42.0))?;
let some_result = some.get(&mut store);
println!("`some` value after `set`: {:?}", some_result);
assert_eq!(some_result, Value::F32(42.0));
Ok(())
}
#[test]
fn test_exported_global() -> Result<(), Box<dyn std::error::Error>> {
main()
}