⭐️ Instantiating a Wasm module
This example illustrates the basics of using Wasmer through a "Hello World"-like project.
In this example we will be building a "Hello World"-like project. WebAssembly only supports passing integers and floats directly right now, thus to keep it simple we will be writing a host application that calls the add_one function of a guest Wasm module, which adds 1 to the value passed as a parameter, and returns the result.
The goal here is to show you the basics of using Wasmer, we'll focus on the steps required to get an instance out of a Wasm module.
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++
Ruby
The final Rust code for this example can be found on Github: instance.rs.
Please take a look at the setup steps for Rust.
1
cargo new instance
2
cd instance
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: instance.go.
Please take a look at the setup steps for Go.
1
mkdir wasmer-example-instance
2
cd wasmer-example-instance
3
go mod init github.com/$USER/wasmer-example-instance
Copied!
The final Python code for this example can be found on Github: instance.py.
Please take a look at the setup steps for Python.
1
mkdir wasmer-example-instance
2
cd wasmer-example-instance
3
pip install wasmer wasmer_compiler_cranelift
Copied!
The final PHP code for this example can be found on Github: instance.py.
Please take a look at the setup steps for PHP.
1
mkdir wasmer-example-instance
2
cd wasmer-example-instance
3
composer init --name=wasmer-project-instance
4
composer require wasm/wasm
Copied!
The final C code for this example can be found on Github: instance.c.
Please take a look at the setup steps for C/C++.
1
mkdir wasmer-example-instance
2
cd wasmer-example-instance
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: instance instance.o
6
instance: instance.o
7
8
.PHONY: clean
9
.SILENT: clean
10
clean:
11
rm -f instance.o instance
Copied!
Wasmer C API includes the wasmer.h header file that you need to include to start using Wasm in C.
The final Ruby code for this example can be found on Github: instance.rb.
Please take a look at the setup steps for Ruby.
1
gem install wasmer
Copied!
Now that we have everything set up, let's go ahead and try it out!

Loading the Wasm module

The first step will be to load the Wasm module we want to use. This is done by having its contents loaded as bytes:
Rust
Go
Python
PHP
C/C++
Ruby
1
let wasm_bytes = wat2wasm(br#"
2
(module
3
(type $add_one_t (func (param i32) (result i32)))
4
(func $add_one_f (type $add_one_t) (param $value i32) (result i32)
5
local.get $value
6
i32.const 1
7
i32.add)
8
(export "add_one" (func $add_one_f)))
9
"#)?;
Copied!
Here we are using the text representation of the Wasm module. Wasmer wants to have a binary representation of the module so we have to use wat2wasm to do the translation.
1
wasmBytes := []byte(`
2
(module
3
(type $add_one_t (func (param i32) (result i32)))
4
(func $add_one_f (type $add_one_t) (param $value i32) (result i32)
5
local.get $value
6
i32.const 1
7
i32.add)
8
(export "add_one" (func $add_one_f)))
9
`)
Copied!
1
wasm_bytes = wat2wasm(
2
"""
3
(module
4
(type $add_one_t (func (param i32) (result i32)))
5
(func $add_one_f (type $add_one_t) (param $value i32) (result i32)
6
local.get $value
7
i32.const 1
8
i32.add)
9
(export "add_one" (func $add_one_f)))
10
"""
11
)
Copied!
1
$wasmBytes = Wasm\Wat::wasm(<<<'WAT'
2
(module
3
(type $add_one_t (func (param i32) (result i32)))
4
(func $add_one_f (type $add_one_t) (param $value i32) (result i32)
5
local.get $value
6
i32.const 1
7
i32.add)
8
(export "add_one" (func $add_one_f)))
9
WAT);
Copied!
1
const char *wat_string =
2
"(module\n"
3
" (type $add_one_t (func (param i32) (result i32)))\n"
4
" (func $add_one_f (type $add_one_t) (param $value i32) (result i32)\n"
5
" local.get $value\n"
6
" i32.const 1\n"
7
" i32.add)\n"
8
" (export \"add_one\" (func $add_one_f)))";
9
10
wasm_byte_vec_t wat;
11
wasm_byte_vec_new(&wat, strlen(wat_string), wat_string);
12
wasm_byte_vec_t wasm_bytes;
13
wat2wasm(&wat, &wasm_bytes);
Copied!
1
wasm_bytes = Wasmer::wat2wasm(
2
(<<~WAST)
3
(module
4
(type $add_one_t (func (param i32) (result i32)))
5
(func $add_one_f (type $add_one_t) (param $value i32) (result i32)
6
local.get $value
7
i32.const 1
8
i32.add)
9
(export "add_one" (func $add_one_f)))
10
WAST
11
)
Copied!
Let's assume we have the binary version of the module (i.e the .wasm file), here is how we would have loaded it:
Rust
Go
Python
PHP
C/C++
Ruby
1
let wasm_bytes = std::fs::read("./path/to/module.wasm")?;
Copied!
1
wasmBytes, err := ioutil.ReadFile("./path/to/module.wasm")
Copied!
1
wasmBytes = open('./path/to/module.wasm', 'rb').read()
Copied!
1
$wasmBytes = file_get_contents('./path/to/module.wasm');
2
3
if (false === $wasmBytes) {
4
echo '> Error loading module!'.PHP_EOL;
5
6
exit(1);
7
}
Copied!
1
FILE* file = fopen("module.wasm", "rb");
2
3
if (!file) {
4
printf("> Error loading module!\n");
5
6
return 1;
7
}
8
9
fseek(file, 0L, SEEK_END);
10
size_t file_size = ftell(file);
11
fseek(file, 0L, SEEK_SET);
12
13
wasm_byte_vec_t wasm_bytes;
14
wasm_byte_vec_new_uninitialized(&wasm_bytes, file_size);
15
16
if (fread(wasm_bytes.data, file_size, 1, file) != 1) {
17
printf("> Error loading module!\n");
18
19
return 1;
20
}
21
22
fclose(file);
Copied!
1
file = File.expand_path "greet.wasm", File.dirname(__FILE__)
2
bytes = IO.read file, mode: "rb"
Copied!

Compiling the Wasm module

The next step will be to compile the module. To do this, we'll need two things: the Wasm module as bytes and a Store.
The Store is a representation of the actual state of the module: it represents the state of every entity in the module during its lifecycle. It also holds the engine which is what will be used to actually compile the module.
Here is how we can create the store and compile the module:
Rust
Go
Python
PHP
C/C++
Ruby
1
let store = Store::default();
2
let module = Module::new(&store, wasm_bytes)?;
Copied!
We are creating a store using the default settings provided by Wasmer. In some cases, you may want to use a specific engine or compiler. Here is how you would do:
1
let engine = Universal::new(&Cranelift::default()).engine();
2
let store = Store::new(&engine);
3
let module = Module::new(&store, wasm_bytes)?;
Copied!
We created a store with the Universal engine and the Cranelift compiler with its default configuration. These are good defaults but it will be a good thing to adapt this configuration to your needs.
1
engine := wasmer.NewEngine()
2
store := wasmer.NewStore(engine)
3
module, err := wasmer.NewModule(store, wasmBytes)
4
5
if err != nil {
6
fmt.Println("Failed to compile module:", err)
7
}
Copied!
1
from wasmer_compiler_cranelift import Compiler
2
3
engine = engine.JIT(Compiler)
4
store = Store(engine)
5
module = Module(store, wasm_bytes)
Copied!
1
$engine = Wasm\Engine::new();
2
$store = Wasm\Store::new($engine);
3
$module = Wasm\Module::new($store, $wasmBytes);
Copied!
1
wasm_engine_t* engine = wasm_engine_new();
2
wasm_store_t* store = wasm_store_new(engine);
3
wasm_module_t* module = wasm_module_new(store, &wasm_bytes);
4
5
if (!module) {
6
printf("> Error compiling module!\n");
7
8
return 1;
9
}
Copied!
1
store = Wasmer::Store.new
2
module_ = Wasmer::Module.new store, wasm_bytes
3
4
raise "Error" unless module
Copied!

Creating an instance of the module

We are now close to having the module run in our Rust host.
The last step will be to create an Instance out of the Wasm module. As for the previous step, here we need more than just the compiled module: we also need to define imports.
In fact, Wasm modules can define entities they need to work properly. These are called imports. In this example we don't need any of them but we still need to define an empty set and use it to instantiate the module:
Rust
Go
Python
PHP
C/C++
Ruby
1
let import_object = imports! {};
2
let instance = Instance::new(&module, &import_object)?;
Copied!
1
importObject := wasmer.NewImportObject()
2
instance, err := wasmer.NewInstance(module, importObject)
Copied!
1
instance = Instance(module)
Copied!
1
$instance = Wasm\Instance::new($store, $module);
Copied!
1
wasm_extern_vec_t imports = WASM_EMPTY_VEC;
2
wasm_instance_t* instance = wasm_instance_new(store, module, &imports, NULL);
3
4
if (!instance) {
5
printf("> Error instantiating module %d!\n");
6
7
return 1;
8
}
Copied!
1
import_object = Wasmer::ImportObject.new
2
instance = Wasmer::Instance.new module_, import_object
3
4
raise "Error" unless instance
Copied!

Running

We now have everything we need to run the Wasm module, let's do it!
Rust
Go
Python
PHP
C/C++
Ruby
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
Calling `add_one` function...
4
Results of `add_one`: 2
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 instance --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
Calling `add_one` function...
4
Results of `add_one`: 2
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_instance_test.go
Copied!
You should be able to run it using the python instance.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/instance.py
Copied!
You should be able to run it using the php instance.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=instance test-doc-examples
Copied!
You should be able to run it using the make clean instance && ./instance command. The output should look like this:
1
Creating the store...
2
Compiling module...
3
Creating imports...
4
Instantiating module...
5
Retrieving exports...
6
Calling `add_one` function...
7
Results of `add_one`: 2
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/instance.c
3
make clean instance
4
./instance
Copied!
You should be able to run it using the ruby instance.rb command.
If you want to run the examples from the Wasmer Ruby repository codebase directly, you can also do:
1
git clone https://github.com/wasmerio/wasmer-ruby.git
2
cd wasmer-ruby
3
ruby examples/instance.rb
Copied!
Last modified 4mo ago