✏️ Using guest (exported) globals
A Wasm module can export entities, like functions, memories, globals and tables. This example illustrates how to use exported globals.
In this example we'll be using a simple Wasm module which exports some globals.
Globals are probably the simplest entity we'll encounter in Wasm modules but there is still some interesting things to talk about. For example, globals come in two flavors:
    Immutable globals (const)
    Mutable globals (var)
We will cover both in this example.
First we are going to want to initialize a new project. To do this we can navigate to our project folder, or create one. In this example, we will create a new project. Lets create it and navigate to it:
Rust
Go
Python
PHP
C/C++
The final Rust code for this example can be found on Github: exports_global.rs.
Please take a look at the setup steps for Rust.
1
cargo new exports-global
2
cd exports-global
Copied!
We have to modify Cargo.toml to add the Wasmer dependencies as shown below:
1
[dependencies]
2
# The Wasmer API
3
wasmer = "2.0"
Copied!
The final Go code for this example can be found on Github: exports_global.go.
Please take a look at the setup steps for Go.
1
mkdir wasmer-example-imports-exports
2
cd wasmer-example-imports-exports
3
go mod init github.com/$USER/wasmer-example-imports-exports
Copied!
The final Python code for this example can be found on Github: exports_global.py.
Please take a look at the setup steps for Python.
1
mkdir wasmer-example-imports-exports
2
cd wasmer-example-imports-exports
3
pip install wasmer wasmer_compiler_cranelift
Copied!
The final PHP code for this example can be found on Github: exports-global.php.
Please take a look at the setup steps for PHP.
1
mkdir wasmer-example-exports-globals
2
cd wasmer-example-exports-globals
3
composer init --name=wasmer-example-exports-globals
4
composer require wasm/wasm
Copied!
The final C code for this example can be found on Github: exports-global.c.
Please take a look at the setup steps for C/C++.
1
mkdir wasmer-example-exports-global
2
cd wasmer-example-exports-global
3
vim Makefile
Copied!
Let's create a simple Makefile:
1
CFLAGS = -g -I$(shell $(WASMER_DIR)/bin/wasmer config --includedir)
2
LDFLAGS = -Wl,-rpath,$(shell $(WASMER_DIR)/bin/wasmer config --libdir)
3
LDLIBS = $(shell $(WASMER_DIR)/bin/wasmer config --libs)
4
5
.SILENT: exports-global exports-global.o
6
exports-global: exports-global.o
7
8
.PHONY: clean
9
.SILENT: clean
10
clean:
11
rm -f exports-global.o exports-global
Copied!
Now that we have everything set up, let's go ahead and try it out!

Querying types information

The first interesting thing to do is to query their type information in order to know if they are mutable or not. Our module exports two globals, one and some. Which one is mutable and which one is not?
Rust
Go
Python
PHP
C/C++
1
let one = instance.exports.get_global("one")?;
2
let some = instance.exports.get_global("some")?;
3
4
let one_type = one.ty();
5
let some_type = some.ty();
6
7
println!("one type: {:?} {:?}", one_type.mutability, one_type.ty);
8
println!("some type: {:?} {:?}", some_type.mutability, some_type.ty);
Copied!
1
one, err := instance.Exports.GetGlobal("one")
2
3
if err != nil {
4
panic(fmt.Sprintln("Failed to retrieve the `one` global:", err))
5
}
6
7
some, err := instance.Exports.GetGlobal("some")
8
9
if err != nil {
10
panic(fmt.Sprintln("Failed to retrieve the `some` global:", err))
11
}
12
13
oneType := one.Type()
14
someType := some.Type()
15
16
fmt.Printf(
17
"`one` type: %s %s\n",
18
oneType.Mutability(),
19
oneType.ValueType().Kind().String()
20
)
21
fmt.Printf(
22
"`some` type: %s %s\n",
23
someType.Mutability(),
24
someType.ValueType().Kind().String()
25
)
Copied!
1
one = instance.exports.one
2
some = instance.exports.some
3
4
one_type = one.type
5
assert one_type.type == Type.F32
6
assert one_type.mutable == False
7
8
some_type = some.type
9
assert some_type.type == Type.F32
10
assert some_type.mutable == True
Copied!
1
$exports = $instance->exports();
2
$one = (new Wasm\Extern($exports[0]))->asGlobal();
3
$some = (new Wasm\Extern($exports[1]))->asGlobal();
4
5
$oneType = $one->type();
6
assert($oneType->mutability() === GlobalType::MUTABILITY_CONST);
7
8
$someType = $some->type();
9
assert($oneType->mutability() === GlobalType::MUTABILITY_VAR);
Copied!
1
wasm_mutability_t one_mutability = wasm_globaltype_mutability(one_type);
2
const wasm_valtype_t* one_content = wasm_globaltype_content(one_type);
3
wasm_valkind_t one_kind = wasm_valtype_kind(one_content);
4
5
wasm_mutability_t some_mutability = wasm_globaltype_mutability(some_type);
6
const wasm_valtype_t* some_content = wasm_globaltype_content(some_type);
7
wasm_valkind_t some_kind = wasm_valtype_kind(some_content);
8
9
printf(
10
"`one` type: %s %hhu\n",
11
one_mutability == WASM_CONST ? "const" : "",
12
one_kind
13
);
14
15
printf(
16
"`some` type: %s %hhu\n",
17
some_mutability == WASM_CONST ? "const" : "",
18
some_kind
19
);
Copied!

Getting globals values

The global API is straightforward: it provides a dedicated method to get the value of a given global. Look how easy it is:
Rust
Go
Python
PHP
C/C++
1
let some_value = some.get();
2
3
println!("`some` value: {:?}", some_value);
Copied!
1
someValue, err := some.Get()
2
3
if err != nil {
4
panic(fmt.Sprintln("Failed to get the `some` global value:", err))
5
}
6
7
fmt.Printf("`some` value: %.1f\n", someValue)
Copied!
1
some_value = some.value
2
3
assert some_value == 0.0
Copied!
1
$someValue = $some->get()->value();
2
3
assert($someValue === 0);
Copied!
1
wasm_val_t some_value;
2
wasm_global_get(some, &some_value);
3
4
printf("`some` value: %.1f\n", some_value.of.f32);
Copied!

Setting globals

As we said before, globals come in two flavor. Immutable globals, for which we can only set a value once and mutable ones.
First we'll try to set the value of a immutable global and see what happens:
Rust
Go
Python
PHP
C/C++
1
let result = one.set(Value::F32(42.0));
2
3
assert_eq!(
4
result.expect_err("Expected an error").message(),
5
"Attempted to set an immutable global"
6
);
Copied!
1
err = one.Set(float32(42.0), wasmer.F32)
2
3
if err == nil {
4
panic(fmt.Sprintln("Setting value to `one` did not error"))
5
}
Copied!
1
try:
2
one.value = 42.0
3
except RuntimeError as err:
4
assert str(err) == 'The global variable is not mutable, cannot set a new value'
5
else:
6
assert False
Copied!
1
try {
2
$one->set(42.0);
3
} catch(\Wasm\Exception\RuntimeException $exception) {
4
assert($exception->getMessage() === 'RuntimeError: Attempted to set an immutable global');
5
}
Copied!
1
wasm_val_t one_set_value = WASM_F32_VAL(42);
2
wasm_global_set(one, &one_set_value);
3
4
int error_length = wasmer_last_error_length();
5
if (error_length > 0) {
6
char *error_message = malloc(error_length);
7
wasmer_last_error_message(error_message, error_length);
8
9
printf("Attempted to set an immutable global: `%s`\n", error_message);
10
}
Copied!
As you can see here, trying to set a value on a immutable global will always lead to an error.
Now let's see how to correctly set a value on a mutable global:
Rust
Go
Python
PHP
C/C++
1
some.set(Value::F32(21.0))?;
Copied!
1
err = some.Set(float32(42.0), wasmer.F32)
2
3
if err != nil {
4
panic(fmt.Sprintln("Failed to set the `some` global value:", err))
5
}
Copied!
1
some.value = 21.0
Copied!
1
$some->set(42.0);
Copied!
1
wasm_val_t some_set_value = WASM_F32_VAL(21);
2
wasm_global_set(some, &some_set_value);
Copied!

Running

We now have everything we need to run the Wasm module, let's do it!
Rust
Go
Python
PHP
C/C++
You should be able to run it using the cargo run command. The output should look like this:
1
Compiling module...
2
Instantiating module...
3
Getting globals types information...
4
`one` type: Const F32
5
`some` type: Var F32
6
Getting global values...
7
`one` value: 1.0
8
`some` value: F32(0.0)
9
Setting global values...
10
`one` value after `set`: F32(1.0)
11
`some` value after `set_some`: F32(21.0)
12
`some` value after `set`: F32(42.0)
Copied!
If you want to run the examples from the Wasmer repository codebase directly, you can also do:
1
git clone https://github.com/wasmerio/wasmer.git
2
cd wasmer
3
cargo run --example exported-function --release --features "cranelift"
Copied!
You should be able to run it using the go run main.go command. The output should look like this:
1
Compiling module...
2
Instantiating module...
3
Getting globals types information...
4
`one` type: const f32
5
`some` type: var f32
6
Getting global values...
7
`one` value: 1.0
8
`some` value: 0.0
9
Setting global values...
10
`one` value: 1.0
11
`some` value after `set_some`: 21.0
12
`some` value after `set`: 42.0
Copied!
If you want to run the examples from the Wasmer repository codebase directly, you can also do:
1
git clone https://github.com/wasmerio/wasmer-go.git
2
cd wasmer-go
3
go test examples/example_exports_global_test.go
Copied!
You should be able to run it using the python exports_global.py command.
If you want to run the examples from the Wasmer repository codebase directly, you can also do:
1
git clone https://github.com/wasmerio/wasmer-python.git
2
cd wasmer-python
3
python examples/exports_global.py
Copied!
You should be able to run it using the php exports-global.php command.
If you want to run the examples from the Wasmer PHP repository codebase directly, you can also do:
1
git clone https://github.com/wasmerio/wasmer-php.git
2
cd wasmer-php
3
make EXAMPLE=exports-global test-doc-examples
Copied!
You should be able to run it using the make clean exports-global && ./exports-global command. The output should look like this:
1
Creating the store...
2
Compiling module...
3
Creating imports...
4
Instantiating module...
5
Retrieving exports...
6
Getting globals types information...
7
`one` type: const 2
8
`some` type: 2
9
Getting global values...`one` value: 1.0
10
`some` value: 0.0
11
Setting global values...
12
Attempted to set an immutable global: `RuntimeError: Attempted to set an immutable global`
13
`some` value: 0.0
Copied!
If you want to run the examples from the Wasmer repository codebase directly, you can also do:
1
git clone https://github.com/wasmerio/wasmer.git
2
cd wasmer/lib/c-api/examples/exports-global.c
3
make clean exports-global
4
./exports-global
Copied!
Last modified 4mo ago