Working with anyref
You can also browse this source code online and clone the wasmtime repository to run the example locally.
This example demonstrates using anyref
values.
anyref.wat
(module
(table $table (export "table") 10 anyref)
(global $global (export "global") (mut anyref) (ref.null any))
(func (export "take_anyref") (param anyref)
nop
)
(func (export "return_anyref") (result anyref)
i32.const 42
ref.i31
)
)
anyref.cc
/*
Example of using `anyref` values.
You can build the example using CMake:
mkdir build && (cd build && cmake .. && \
cmake --build . --target wasmtime-anyref-cpp)
And then run it:
build/wasmtime-anyref-cpp
*/
#include <fstream>
#include <iostream>
#include <sstream>
#include <wasmtime.hh>
using namespace wasmtime;
std::string readFile(const char *name) {
std::ifstream watFile;
watFile.open(name);
std::stringstream strStream;
strStream << watFile.rdbuf();
return strStream.str();
}
int main() {
std::cout << "Initializing...\n";
Config config;
config.wasm_reference_types(true);
config.wasm_function_references(true);
config.wasm_gc(true);
Engine engine(std::move(config));
Store store(engine);
std::cout << "Compiling module...\n";
auto wat = readFile("examples/anyref.wat");
Module module = Module::compile(engine, wat).unwrap();
std::cout << "Instantiating module...\n";
Instance instance = Instance::create(store, module, {}).unwrap();
std::cout << "Creating new `anyref` from i31...\n";
// Create an i31ref wrapping 1234
auto cx = store.context();
AnyRef i31 = AnyRef::i31(cx, 1234);
Val anyref_val(i31);
auto opt_any = anyref_val.anyref(cx);
if (!opt_any || !opt_any->u31(cx) || *opt_any->u31(cx) != 1234) {
std::cerr << "> Error creating i31 anyref\n";
return 1;
}
std::cout << "Touching `anyref` table...\n";
Table table = std::get<Table>(*instance.get(store, "table"));
table.set(store, 3, anyref_val).unwrap();
auto elem_opt = table.get(store, 3);
if (!elem_opt) {
std::cerr << "> Error getting table element\n";
return 1;
}
auto elem_any = elem_opt->anyref(cx);
if (!elem_any || !elem_any->u31(cx) || *elem_any->u31(cx) != 1234) {
std::cerr << "> Error verifying table element\n";
return 1;
}
std::cout << "Touching `anyref` global...\n";
Global global = std::get<Global>(*instance.get(store, "global"));
global.set(store, anyref_val).unwrap();
Val global_val = global.get(store);
auto global_any = global_val.anyref(cx);
if (!global_any || !global_any->u31(cx) || *global_any->u31(cx) != 1234) {
std::cerr << "> Error verifying global value\n";
return 1;
}
std::cout << "Passing `anyref` into func...\n";
Func take_anyref = std::get<Func>(*instance.get(store, "take_anyref"));
take_anyref.call(store, {anyref_val}).unwrap();
std::cout << "Getting `anyref` from func...\n";
Func return_anyref = std::get<Func>(*instance.get(store, "return_anyref"));
auto results = return_anyref.call(store, {}).unwrap();
if (results.size() != 1) {
std::cerr << "> Unexpected number of results\n";
return 1;
}
auto ret_any = results[0].anyref(cx);
if (!ret_any || !ret_any->u31(cx) || *ret_any->u31(cx) != 42) {
std::cerr << "> Error verifying returned anyref\n";
return 1;
}
std::cout << "GCing within the store...\n";
store.context().gc();
std::cout << "Done.\n";
return 0;
}