• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <iostream>
2 #include <fstream>
3 #include <cstdlib>
4 #include <string>
5 #include <cinttypes>
6 
7 #include "wasm.hh"
8 
9 // Print a Wasm value
operator <<(std::ostream & out,const wasm::Val & val)10 auto operator<<(std::ostream& out, const wasm::Val& val) -> std::ostream& {
11   switch (val.kind()) {
12     case wasm::I32: {
13       out << val.i32();
14     } break;
15     case wasm::I64: {
16       out << val.i64();
17     } break;
18     case wasm::F32: {
19       out << val.f32();
20     } break;
21     case wasm::F64: {
22       out << val.f64();
23     } break;
24     case wasm::ANYREF:
25     case wasm::FUNCREF: {
26       if (val.ref() == nullptr) {
27         out << "null";
28       } else {
29         out << "ref(" << val.ref() << ")";
30       }
31     } break;
32   }
33   return out;
34 }
35 
36 // A function to be called from Wasm code.
print_callback(const wasm::Val args[],wasm::Val results[])37 auto print_callback(
38   const wasm::Val args[], wasm::Val results[]
39 ) -> wasm::own<wasm::Trap> {
40   std::cout << "Calling back..." << std::endl << "> " << args[0] << std::endl;
41   results[0] = args[0].copy();
42   return nullptr;
43 }
44 
45 
46 // A function closure.
closure_callback(void * env,const wasm::Val args[],wasm::Val results[])47 auto closure_callback(
48   void* env, const wasm::Val args[], wasm::Val results[]
49 ) -> wasm::own<wasm::Trap> {
50   auto i = *reinterpret_cast<int*>(env);
51   std::cout << "Calling back closure..." << std::endl;
52   std::cout << "> " << i << std::endl;
53   results[0] = wasm::Val::i32(static_cast<int32_t>(i));
54   return nullptr;
55 }
56 
57 
run()58 void run() {
59   // Initialize.
60   std::cout << "Initializing..." << std::endl;
61   auto engine = wasm::Engine::make();
62   auto store_ = wasm::Store::make(engine.get());
63   auto store = store_.get();
64 
65   // Load binary.
66   std::cout << "Loading binary..." << std::endl;
67   std::ifstream file("callback.wasm");
68   file.seekg(0, std::ios_base::end);
69   auto file_size = file.tellg();
70   file.seekg(0);
71   auto binary = wasm::vec<byte_t>::make_uninitialized(file_size);
72   file.read(binary.get(), file_size);
73   file.close();
74   if (file.fail()) {
75     std::cout << "> Error loading module!" << std::endl;
76     exit(1);
77   }
78 
79   // Compile.
80   std::cout << "Compiling module..." << std::endl;
81   auto module = wasm::Module::make(store, binary);
82   if (!module) {
83     std::cout << "> Error compiling module!" << std::endl;
84     exit(1);
85   }
86 
87   // Create external print functions.
88   std::cout << "Creating callback..." << std::endl;
89   auto print_type = wasm::FuncType::make(
90     wasm::ownvec<wasm::ValType>::make(wasm::ValType::make(wasm::I32)),
91     wasm::ownvec<wasm::ValType>::make(wasm::ValType::make(wasm::I32))
92   );
93   auto print_func = wasm::Func::make(store, print_type.get(), print_callback);
94 
95   // Creating closure.
96   std::cout << "Creating closure..." << std::endl;
97   int i = 42;
98   auto closure_type = wasm::FuncType::make(
99     wasm::ownvec<wasm::ValType>::make(),
100     wasm::ownvec<wasm::ValType>::make(wasm::ValType::make(wasm::I32))
101   );
102   auto closure_func = wasm::Func::make(store, closure_type.get(), closure_callback, &i);
103 
104   // Instantiate.
105   std::cout << "Instantiating module..." << std::endl;
106   wasm::Extern* imports[] = {print_func.get(), closure_func.get()};
107   auto instance = wasm::Instance::make(store, module.get(), imports);
108   if (!instance) {
109     std::cout << "> Error instantiating module!" << std::endl;
110     exit(1);
111   }
112 
113   // Extract export.
114   std::cout << "Extracting export..." << std::endl;
115   auto exports = instance->exports();
116   if (exports.size() == 0 || exports[0]->kind() != wasm::EXTERN_FUNC || !exports[0]->func()) {
117     std::cout << "> Error accessing export!" << std::endl;
118     exit(1);
119   }
120   auto run_func = exports[0]->func();
121 
122   // Call.
123   std::cout << "Calling export..." << std::endl;
124   wasm::Val args[] = {wasm::Val::i32(3), wasm::Val::i32(4)};
125   wasm::Val results[1];
126   if (run_func->call(args, results)) {
127     std::cout << "> Error calling function!" << std::endl;
128     exit(1);
129   }
130 
131   // Print result.
132   std::cout << "Printing result..." << std::endl;
133   std::cout << "> " << results[0].i32() << std::endl;
134 
135   // Shut down.
136   std::cout << "Shutting down..." << std::endl;
137 }
138 
139 
main(int argc,const char * argv[])140 int main(int argc, const char* argv[]) {
141   run();
142   std::cout << "Done." << std::endl;
143   return 0;
144 }
145 
146