↪️ Calling guest (exported) functions
A Wasm module can export entities, like functions, memories, globals and tables. This example illustrates how to call exported functions.
In this example we'll see how to use exported functions.
Exported function are the entities you will probably use the most: they will be your entrypoint to calling Wasm module logic.
Exported function come in two flavors:
- Dynamic functions;
- Typed functions.
We'll cover both flavors 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++
Ruby
cargo new exports-function
cd exports-function
We have to modify
Cargo.toml
to add the Wasmer dependencies as shown below:[dependencies]
# The Wasmer API
wasmer = "3.0"
mkdir wasmer-example-exports-function
cd wasmer-example-exports-function
go mod init github.com/$USER/wasmer-example-exports-function
mkdir wasmer-example-exports-function
cd wasmer-example-exports-function
pip install wasmer wasmer_compiler_cranelift
mkdir wasmer-example-exports-function
cd wasmer-example-exports-function
composer init --name=wasmer-example-exports-function
composer require wasm/wasm
mkdir wasmer-example-exports-function
cd wasmer-example-exports-function
vim Makefile
Let's create a simple
Makefile
:CFLAGS = -g -I$(shell $(WASMER_DIR)/bin/wasmer config --includedir)
LDFLAGS = -Wl,-rpath,$(shell $(WASMER_DIR)/bin/wasmer config --libdir)
LDLIBS = $(shell $(WASMER_DIR)/bin/wasmer config --libs)
.SILENT: exports-function exports-function.o
exports-function: exports-function.o
.PHONY: clean
.SILENT: clean
clean:
rm -f exports-function.o exports-function
gem install wasmer
Now that we have everything set up, let's go ahead and try it out!
We'll start by fetching the guest function and see how to call it using the dynamic flavor. Our Wasm module exports a
sum
function, let's get and call it:Rust
Go
Python
PHP
C/C++
Ruby
let sum = instance.exports.get_function("sum")?;
let args = [Value::I32(1), Value::I32(2)];
let result: Box<[Val]> = sum.call(&mut store, &args)?;
sum, err := instance.Exports.GetRawFunction("sum")
if err != nil {
panic(fmt.Sprintf("Failed to get the `%s` function: %s\n", name, err))
}
result, err := sum.Call(1, 2)
(not possible)
$firstArg = Wasm\Module\Val::newI32(1);
$secondArg = Wasm\Module\Val::newI32(2);
$args = new Wasm\Vec\Val([$firstArg->inner(), $secondArg->inner()]);
$result = $sum($args);
wasm_val_t args_val[2] = { WASM_I32_VAL(3), WASM_I32_VAL(4) };
wasm_val_t results_val[1] = { WASM_INIT_VAL };
wasm_val_vec_t args = WASM_ARRAY_VEC(args_val);
wasm_val_vec_t results = WASM_ARRAY_VEC(results_val);
if (wasm_func_call(sum_func, &args, &results)) {
printf("> Error calling the `sum` function!\n");
return 1;
}
sum = instance.exports.sum
results = sum.call(1, 2)
Easy right?
Both example look nice but it does not seem like we are using standard functions. In fact, we are calling an external entity. With the native flavor we can get something that feels more like we are using functions as if they were provided by the host directly.
Let's have a look at this.
Let's continue with our previous
sum
function and see how we can make interacting with it better. To do so, we'll be using the native flavor. With this flavor, passing arguments and getting result will feel more natural.To use this flavor, we have the choice of fetching the function again or transforming the one we already have into a native function:
Rust
Go
Python
PHP
C/C++
Ruby
let sum: TypedFunction<(i32, i32), i32> = sum.typed(&store)?;
let result: i32 = sum.call(3, 4)?;
Here we reused the previously fetched function and turned it into a typed one. We could have directly fetched it as a typed function:
let sum: TypedFunction<(i32, i32), i32> = instance
.exports
.get_typed_function::<(i32, i32), i32>("sum")?;
sumNative := sum.Native()
result, err = sumNative(3, 4)
Here we reused the previously fetched function and turned it into a native one. We could have directly fetched it as a native function:
sum, err := instance.Exports.GetFunction("sum")
if err != nil {
panic(fmt.Sprintf(
"Failed to get the `%s` function: %s\n",
name,
err
))
}
sum = instance.exports.sum
result = sum(3, 4)
(not possible)
(not possible)
(not possible)
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:Compiling module...
Instantiating module...
Calling `sum` function...
Results: [I32(3)]
Calling `sum` function (natively)...
Results: 7
git clone https://github.com/wasmerio/wasmer.git
cd wasmer
cargo run --example exported-function --release --features "cranelift"
You should be able to run it using the
go run main.go
command. The output should look like this:Compiling module...
Instantiating module...
Calling `sum` function...
Result of the `sum` function: 3
Calling `sum` function (natively)...
Result of the `sum` function: 7
git clone https://github.com/wasmerio/wasmer-go.git
cd wasmer-go
go test examples/example_exports_function_test.go
You should be able to run it using the
python exports_function.py
command.git clone https://github.com/wasmerio/wasmer-python.git
cd wasmer-python
python examples/exports_function.py
You should be able to run it using the
php exports-function.php
command.git clone https://github.com/wasmerio/wasmer-php.git
cd wasmer-php
make EXAMPLE=exports-function test-doc-examples
You should be able to run it using the
make clean exports-function && ./exports-function
command. The output should look like this:Creating the store...
Compiling module...
Creating imports...
Instantiating module...
Retrieving exports...
Retrieving the `sum` function...
Calling `sum` function...
Results of `sum`: 7
git clone https://github.com/wasmerio/wasmer.git
cd wasmer/lib/c-api/examples/exports-function.c
make clean exports-function
./exports-function
You should be able to run it using the
ruby exports_function.rb
command.git clone https://github.com/wasmerio/wasmer-ruby.git
cd wasmer-ruby
ruby examples/exports_function.rb
Last modified 7mo ago