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 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 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