forked from wasmerio/wasmer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
exports_global.rs
143 lines (121 loc) · 4.37 KB
/
exports_global.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//! 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, Value};
use wasmer_compiler::Universal;
use wasmer_compiler_cranelift::Cranelift;
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.
// Note that we don't need to specify the engine/compiler if we want to use
// the default provided by Wasmer.
// You can use `Store::default()` for that.
let store = Store::new_with_engine(&Universal::new(Cranelift::default()).engine());
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(&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();
let some_type = some.ty();
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 = instance
.exports
.get_function("get_one")?
.native::<(), f32>()?;
let one_value = get_one.call()?;
let some_value = some.get();
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(Value::F32(42.0));
assert_eq!(
result.expect_err("Expected an error").message(),
"Attempted to set an immutable global"
);
let one_result = one.get();
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 = instance
.exports
.get_function("set_some")?
.native::<f32, ()>()?;
set_some.call(21.0)?;
let some_result = some.get();
println!("`some` value after `set_some`: {:?}", some_result);
assert_eq!(some_result, Value::F32(21.0));
some.set(Value::F32(42.0))?;
let some_result = some.get();
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()
}