xref: /wasmtime-44.0.1/examples/multi.c (revision b221fca7)
1 /*
2 Example of instantiating of the WebAssembly module and invoking its exported
3 function.
4 
5 You can build using cmake:
6 
7 mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-multi
8 
9 Also note that this example was taken from
10 https://github.com/WebAssembly/wasm-c-api/blob/master/example/multi.c
11 originally
12 */
13 
14 #include <inttypes.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <wasm.h>
19 #include <wasmtime.h>
20 
21 static void exit_with_error(const char *message, wasmtime_error_t *error,
22                             wasm_trap_t *trap);
23 
24 // A function to be called from Wasm code.
25 wasm_trap_t *callback(void *env, wasmtime_caller_t *caller,
26                       const wasmtime_val_t *args, size_t nargs,
27                       wasmtime_val_t *results, size_t nresults) {
28   printf("Calling back...\n");
29   printf("> %" PRIu32 " %" PRIu64 "\n", args[0].of.i32, args[1].of.i64);
30   printf("\n");
31 
32   results[0] = args[1];
33   results[1] = args[0];
34   return NULL;
35 }
36 
37 // A function closure.
38 wasm_trap_t *closure_callback(void *env, wasmtime_caller_t *caller,
39                               const wasmtime_val_t *args, size_t nargs,
40                               wasmtime_val_t *results, size_t nresults) {
41   int i = *(int *)env;
42   printf("Calling back closure...\n");
43   printf("> %d\n", i);
44 
45   results[0].kind = WASMTIME_I32;
46   results[0].of.i32 = (int32_t)i;
47   return NULL;
48 }
49 
50 int main(int argc, const char *argv[]) {
51   // Initialize.
52   printf("Initializing...\n");
53   wasm_engine_t *engine = wasm_engine_new();
54   wasmtime_store_t *store = wasmtime_store_new(engine, NULL, NULL);
55   wasmtime_context_t *context = wasmtime_store_context(store);
56 
57   // Load our input file to parse it next
58   FILE *file = fopen("examples/multi.wat", "r");
59   if (!file) {
60     printf("> Error loading file!\n");
61     return 1;
62   }
63   fseek(file, 0L, SEEK_END);
64   size_t file_size = ftell(file);
65   fseek(file, 0L, SEEK_SET);
66   wasm_byte_vec_t wat;
67   wasm_byte_vec_new_uninitialized(&wat, file_size);
68   if (fread(wat.data, file_size, 1, file) != 1) {
69     printf("> Error loading module!\n");
70     return 1;
71   }
72   fclose(file);
73 
74   // Parse the wat into the binary wasm format
75   wasm_byte_vec_t binary;
76   wasmtime_error_t *error = wasmtime_wat2wasm(wat.data, wat.size, &binary);
77   if (error != NULL)
78     exit_with_error("failed to parse wat", error, NULL);
79   wasm_byte_vec_delete(&wat);
80 
81   // Compile.
82   printf("Compiling module...\n");
83   wasmtime_module_t *module = NULL;
84   error =
85       wasmtime_module_new(engine, (uint8_t *)binary.data, binary.size, &module);
86   if (error)
87     exit_with_error("failed to compile module", error, NULL);
88   wasm_byte_vec_delete(&binary);
89 
90   // Create external print functions.
91   printf("Creating callback...\n");
92   wasm_functype_t *callback_type =
93       wasm_functype_new_2_2(wasm_valtype_new_i32(), wasm_valtype_new_i64(),
94                             wasm_valtype_new_i64(), wasm_valtype_new_i32());
95   wasmtime_func_t callback_func;
96   wasmtime_func_new(context, callback_type, callback, NULL, NULL,
97                     &callback_func);
98   wasm_functype_delete(callback_type);
99 
100   // Instantiate.
101   printf("Instantiating module...\n");
102   wasmtime_extern_t imports[1];
103   imports[0].kind = WASMTIME_EXTERN_FUNC;
104   imports[0].of.func = callback_func;
105   wasmtime_instance_t instance;
106   wasm_trap_t *trap = NULL;
107   error = wasmtime_instance_new(context, module, imports, 1, &instance, &trap);
108   if (error != NULL || trap != NULL)
109     exit_with_error("failed to instantiate", error, trap);
110   wasmtime_module_delete(module);
111 
112   // Extract export.
113   printf("Extracting export...\n");
114   wasmtime_extern_t run;
115   bool ok = wasmtime_instance_export_get(context, &instance, "g", 1, &run);
116   assert(ok);
117   assert(run.kind == WASMTIME_EXTERN_FUNC);
118 
119   // Call.
120   printf("Calling export...\n");
121   wasmtime_val_t args[2];
122   args[0].kind = WASMTIME_I32;
123   args[0].of.i32 = 1;
124   args[1].kind = WASMTIME_I64;
125   args[1].of.i64 = 2;
126   wasmtime_val_t results[2];
127   error = wasmtime_func_call(context, &run.of.func, args, 2, results, 2, &trap);
128   if (error != NULL || trap != NULL)
129     exit_with_error("failed to call run", error, trap);
130 
131   // Print result.
132   printf("Printing result...\n");
133   printf("> %" PRIu64 " %" PRIu32 "\n", results[0].of.i64, results[1].of.i32);
134 
135   assert(results[0].kind == WASMTIME_I64);
136   assert(results[0].of.i64 == 2);
137   assert(results[1].kind == WASMTIME_I32);
138   assert(results[1].of.i32 == 1);
139 
140   // Shut down.
141   printf("Shutting down...\n");
142   wasmtime_store_delete(store);
143   wasm_engine_delete(engine);
144 
145   // All done.
146   printf("Done.\n");
147   return 0;
148 }
149 
150 static void exit_with_error(const char *message, wasmtime_error_t *error,
151                             wasm_trap_t *trap) {
152   fprintf(stderr, "error: %s\n", message);
153   wasm_byte_vec_t error_message;
154   if (error != NULL) {
155     wasmtime_error_message(error, &error_message);
156     wasmtime_error_delete(error);
157   } else {
158     wasm_trap_message(trap, &error_message);
159     wasm_trap_delete(trap);
160   }
161   fprintf(stderr, "%.*s\n", (int)error_message.size, error_message.data);
162   wasm_byte_vec_delete(&error_message);
163   exit(1);
164 }
165