xref: /wasmtime-44.0.1/examples/gcd.c (revision 57ba95e9)
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-gcd
8 */
9 
10 #include <assert.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <wasm.h>
14 #include <wasmtime.h>
15 
16 static void exit_with_error(const char *message, wasmtime_error_t *error,
17                             wasm_trap_t *trap);
18 
main()19 int main() {
20   int ret = 0;
21   // Set up our context
22   wasm_engine_t *engine = wasm_engine_new();
23   assert(engine != NULL);
24   wasmtime_store_t *store = wasmtime_store_new(engine, NULL, NULL);
25   assert(store != NULL);
26   wasmtime_context_t *context = wasmtime_store_context(store);
27 
28   // Load our input file to parse it next
29   FILE *file = fopen("examples/gcd.wat", "r");
30   if (!file) {
31     printf("> Error loading file!\n");
32     return 1;
33   }
34   fseek(file, 0L, SEEK_END);
35   size_t file_size = ftell(file);
36   fseek(file, 0L, SEEK_SET);
37   wasm_byte_vec_t wat;
38   wasm_byte_vec_new_uninitialized(&wat, file_size);
39   if (fread(wat.data, file_size, 1, file) != 1) {
40     printf("> Error loading module!\n");
41     return 1;
42   }
43   fclose(file);
44 
45   // Parse the wat into the binary wasm format
46   wasm_byte_vec_t wasm;
47   wasmtime_error_t *error = wasmtime_wat2wasm(wat.data, wat.size, &wasm);
48   if (error != NULL)
49     exit_with_error("failed to parse wat", error, NULL);
50   wasm_byte_vec_delete(&wat);
51 
52   // Compile and instantiate our module
53   wasmtime_module_t *module = NULL;
54   error = wasmtime_module_new(engine, (uint8_t *)wasm.data, wasm.size, &module);
55   if (module == NULL)
56     exit_with_error("failed to compile module", error, NULL);
57   wasm_byte_vec_delete(&wasm);
58 
59   wasm_trap_t *trap = NULL;
60   wasmtime_instance_t instance;
61   error = wasmtime_instance_new(context, module, NULL, 0, &instance, &trap);
62   if (error != NULL || trap != NULL)
63     exit_with_error("failed to instantiate", error, trap);
64 
65   // Lookup our `gcd` export function
66   wasmtime_extern_t gcd;
67   bool ok = wasmtime_instance_export_get(context, &instance, "gcd", 3, &gcd);
68   assert(ok);
69   assert(gcd.kind == WASMTIME_EXTERN_FUNC);
70 
71   // And call it!
72   int a = 6;
73   int b = 27;
74   wasmtime_val_t params[2];
75   params[0].kind = WASMTIME_I32;
76   params[0].of.i32 = a;
77   params[1].kind = WASMTIME_I32;
78   params[1].of.i32 = b;
79   wasmtime_val_t results[1];
80   error =
81       wasmtime_func_call(context, &gcd.of.func, params, 2, results, 1, &trap);
82   if (error != NULL || trap != NULL)
83     exit_with_error("failed to call gcd", error, trap);
84   assert(results[0].kind == WASMTIME_I32);
85 
86   printf("gcd(%d, %d) = %d\n", a, b, results[0].of.i32);
87 
88   // Clean up after ourselves at this point
89   ret = 0;
90 
91   wasmtime_module_delete(module);
92   wasmtime_store_delete(store);
93   wasm_engine_delete(engine);
94   return ret;
95 }
96 
exit_with_error(const char * message,wasmtime_error_t * error,wasm_trap_t * trap)97 static void exit_with_error(const char *message, wasmtime_error_t *error,
98                             wasm_trap_t *trap) {
99   fprintf(stderr, "error: %s\n", message);
100   wasm_byte_vec_t error_message;
101   if (error != NULL) {
102     wasmtime_error_message(error, &error_message);
103   } else {
104     wasm_trap_message(trap, &error_message);
105   }
106   fprintf(stderr, "%.*s\n", (int)error_message.size, error_message.data);
107   wasm_byte_vec_delete(&error_message);
108   exit(1);
109 }
110