xref: /wasmtime-44.0.1/examples/multi.c (revision 3b7cb6ee)
1 /*
2 Example of instantiating of the WebAssembly module and invoking its exported
3 function.
4 
5 You can compile and run this example on Linux with:
6 
7    cargo build --release -p wasmtime
8    cc examples/multi.c \
9        -I crates/c-api/include \
10        -I crates/c-api/wasm-c-api/include \
11        target/release/libwasmtime.a \
12        -lpthread -ldl -lm \
13        -o multi
14    ./multi
15 
16 Note that on Windows and macOS the command will be similar, but you'll need
17 to tweak the `-lpthread` and such annotations.
18 
19 Also note that this example was taken from
20 https://github.com/WebAssembly/wasm-c-api/blob/master/example/multi.c
21 originally
22 */
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <inttypes.h>
28 #include <wasm.h>
29 #include <wasmtime.h>
30 
31 // A function to be called from Wasm code.
32 wasm_trap_t* callback(
33   const wasm_val_t args[], wasm_val_t results[]
34 ) {
35   printf("Calling back...\n");
36   printf("> %"PRIu32" %"PRIu64"\n", args[0].of.i32, args[1].of.i64);
37   printf("\n");
38 
39   wasm_val_copy(&results[0], &args[1]);
40   wasm_val_copy(&results[1], &args[0]);
41   return NULL;
42 }
43 
44 
45 // A function closure.
46 wasm_trap_t* closure_callback(
47   void* env, const wasm_val_t args[], wasm_val_t results[]
48 ) {
49   int i = *(int*)env;
50   printf("Calling back closure...\n");
51   printf("> %d\n", i);
52 
53   results[0].kind = WASM_I32;
54   results[0].of.i32 = (int32_t)i;
55   return NULL;
56 }
57 
58 
59 int main(int argc, const char* argv[]) {
60   // Initialize.
61   printf("Initializing...\n");
62   wasm_config_t *config = wasm_config_new();
63   assert(config != NULL);
64   wasmtime_config_wasm_multi_value_set(config, true);
65   wasm_engine_t* engine = wasm_engine_new_with_config(config);
66   wasm_store_t* store = wasm_store_new(engine);
67 
68   // Load our input file to parse it next
69   FILE* file = fopen("examples/multi.wat", "r");
70   if (!file) {
71     printf("> Error loading file!\n");
72     return 1;
73   }
74   fseek(file, 0L, SEEK_END);
75   size_t file_size = ftell(file);
76   fseek(file, 0L, SEEK_SET);
77   wasm_byte_vec_t wat;
78   wasm_byte_vec_new_uninitialized(&wat, file_size);
79   if (fread(wat.data, file_size, 1, file) != 1) {
80     printf("> Error loading module!\n");
81     return 1;
82   }
83   fclose(file);
84 
85   // Parse the wat into the binary wasm format
86   wasm_byte_vec_t binary, error;
87   if (wasmtime_wat2wasm(engine, &wat, &binary, &error) == 0) {
88     fprintf(stderr, "failed to parse wat %.*s\n", (int) error.size, error.data);
89     return 1;
90   }
91   wasm_byte_vec_delete(&wat);
92 
93   // Compile.
94   printf("Compiling module...\n");
95   wasm_module_t* module = wasm_module_new(store, &binary);
96   if (!module) {
97     printf("> Error compiling module!\n");
98     return 1;
99   }
100 
101   wasm_byte_vec_delete(&binary);
102 
103   // Create external print functions.
104   printf("Creating callback...\n");
105   wasm_functype_t* callback_type = wasm_functype_new_2_2(
106       wasm_valtype_new_i32(),
107       wasm_valtype_new_i64(),
108       wasm_valtype_new_i64(),
109       wasm_valtype_new_i32()
110   );
111   wasm_func_t* callback_func =
112     wasm_func_new(store, callback_type, callback);
113 
114   wasm_functype_delete(callback_type);
115 
116   // Instantiate.
117   printf("Instantiating module...\n");
118   const wasm_extern_t* imports[] = {wasm_func_as_extern(callback_func)};
119   wasm_instance_t* instance =
120     wasm_instance_new(store, module, imports, NULL);
121   if (!instance) {
122     printf("> Error instantiating module!\n");
123     return 1;
124   }
125 
126   wasm_func_delete(callback_func);
127 
128   // Extract export.
129   printf("Extracting export...\n");
130   wasm_extern_vec_t exports;
131   wasm_instance_exports(instance, &exports);
132   if (exports.size == 0) {
133     printf("> Error accessing exports!\n");
134     return 1;
135   }
136   const wasm_func_t* run_func = wasm_extern_as_func(exports.data[0]);
137   if (run_func == NULL) {
138     printf("> Error accessing export!\n");
139     return 1;
140   }
141 
142   wasm_module_delete(module);
143   wasm_instance_delete(instance);
144 
145   // Call.
146   printf("Calling export...\n");
147   wasm_val_t args[4];
148   args[0].kind = WASM_I32;
149   args[0].of.i32 = 1;
150   args[1].kind = WASM_I64;
151   args[1].of.i64 = 2;
152   wasm_val_t results[2];
153   if (wasm_func_call(run_func, args, results)) {
154     printf("> Error calling function!\n");
155     return 1;
156   }
157 
158   wasm_extern_vec_delete(&exports);
159 
160   // Print result.
161   printf("Printing result...\n");
162   printf("> %"PRIu64" %"PRIu32"\n",
163     results[0].of.i64, results[1].of.i32);
164 
165   assert(results[0].kind == WASM_I64);
166   assert(results[0].of.i64 == 2);
167   assert(results[1].kind == WASM_I32);
168   assert(results[1].of.i32 == 1);
169 
170   // Shut down.
171   printf("Shutting down...\n");
172   wasm_store_delete(store);
173   wasm_engine_delete(engine);
174 
175   // All done.
176   printf("Done.\n");
177   return 0;
178 }
179 
180