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