1#include <iostream> 2#include <fstream> 3#include <cstdlib> 4#include <string> 5#include <cinttypes> 6 7#include "wasm.hh" 8 9// A function to be called from Wasm code. 10auto callback( 11 const wasm::Val args[], wasm::Val results[] 12) -> wasm::own<wasm::Trap> { 13 std::cout << "Calling back..." << std::endl; 14 std::cout << "> " << args[0].i32(); 15 std::cout << " " << args[1].i64(); 16 std::cout << " " << args[2].i64(); 17 std::cout << " " << args[3].i32() << std::endl; 18 results[0] = args[3].copy(); 19 results[1] = args[1].copy(); 20 results[2] = args[2].copy(); 21 results[3] = args[0].copy(); 22 return nullptr; 23} 24 25 26void run() { 27 // Initialize. 28 std::cout << "Initializing..." << std::endl; 29 auto engine = wasm::Engine::make(); 30 auto store_ = wasm::Store::make(engine.get()); 31 auto store = store_.get(); 32 33 // Load binary. 34 std::cout << "Loading binary..." << std::endl; 35 std::ifstream file("multi.wasm"); 36 file.seekg(0, std::ios_base::end); 37 auto file_size = file.tellg(); 38 file.seekg(0); 39 auto binary = wasm::vec<byte_t>::make_uninitialized(file_size); 40 file.read(binary.get(), file_size); 41 file.close(); 42 if (file.fail()) { 43 std::cout << "> Error loading module!" << std::endl; 44 exit(1); 45 } 46 47 // Compile. 48 std::cout << "Compiling module..." << std::endl; 49 auto module = wasm::Module::make(store, binary); 50 if (!module) { 51 std::cout << "> Error compiling module!" << std::endl; 52 exit(1); 53 } 54 55 // Create external print functions. 56 std::cout << "Creating callback..." << std::endl; 57 auto tuple = wasm::ownvec<wasm::ValType>::make( 58 wasm::ValType::make(wasm::I32), 59 wasm::ValType::make(wasm::I64), 60 wasm::ValType::make(wasm::I64), 61 wasm::ValType::make(wasm::I32) 62 ); 63 auto callback_type = 64 wasm::FuncType::make(tuple.deep_copy(), tuple.deep_copy()); 65 auto callback_func = wasm::Func::make(store, callback_type.get(), callback); 66 67 // Instantiate. 68 std::cout << "Instantiating module..." << std::endl; 69 wasm::Extern* imports[] = {callback_func.get()}; 70 auto instance = wasm::Instance::make(store, module.get(), imports); 71 if (!instance) { 72 std::cout << "> Error instantiating module!" << std::endl; 73 exit(1); 74 } 75 76 // Extract export. 77 std::cout << "Extracting export..." << std::endl; 78 auto exports = instance->exports(); 79 if (exports.size() == 0 || exports[0]->kind() != wasm::EXTERN_FUNC || !exports[0]->func()) { 80 std::cout << "> Error accessing export!" << std::endl; 81 exit(1); 82 } 83 auto run_func = exports[0]->func(); 84 85 // Call. 86 std::cout << "Calling export..." << std::endl; 87 wasm::Val args[] = { 88 wasm::Val::i32(1), wasm::Val::i64(2), wasm::Val::i64(3), wasm::Val::i32(4) 89 }; 90 wasm::Val results[4]; 91 if (wasm::own<wasm::Trap> trap = run_func->call(args, results)) { 92 std::cout << "> Error calling function! " << trap->message().get() << std::endl; 93 exit(1); 94 } 95 96 // Print result. 97 std::cout << "Printing result..." << std::endl; 98 std::cout << "> " << results[0].i32(); 99 std::cout << " " << results[1].i64(); 100 std::cout << " " << results[2].i64(); 101 std::cout << " " << results[3].i32() << std::endl; 102 103 assert(results[0].i32() == 4); 104 assert(results[1].i64() == 3); 105 assert(results[2].i64() == 2); 106 assert(results[3].i32() == 1); 107 108 // Shut down. 109 std::cout << "Shutting down..." << std::endl; 110} 111 112 113int main(int argc, const char* argv[]) { 114 run(); 115 std::cout << "Done." << std::endl; 116 return 0; 117} 118 119