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-fuel 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 wasmtime_error_t *error = NULL; 21 22 wasm_config_t *config = wasm_config_new(); 23 assert(config != NULL); 24 wasmtime_config_consume_fuel_set(config, true); 25 26 // Create an *engine*, which is a compilation context, with our configured 27 // options. 28 wasm_engine_t *engine = wasm_engine_new_with_config(config); 29 assert(engine != NULL); 30 wasmtime_store_t *store = wasmtime_store_new(engine, NULL, NULL); 31 assert(store != NULL); 32 wasmtime_context_t *context = wasmtime_store_context(store); 33 34 error = wasmtime_context_set_fuel(context, 10000); 35 if (error != NULL) 36 exit_with_error("failed to set fuel", error, NULL); 37 38 // Load our input file to parse it next 39 FILE *file = fopen("examples/fuel.wat", "r"); 40 if (!file) { 41 printf("> Error loading file!\n"); 42 return 1; 43 } 44 fseek(file, 0L, SEEK_END); 45 size_t file_size = ftell(file); 46 fseek(file, 0L, SEEK_SET); 47 wasm_byte_vec_t wat; 48 wasm_byte_vec_new_uninitialized(&wat, file_size); 49 if (fread(wat.data, file_size, 1, file) != 1) { 50 printf("> Error loading module!\n"); 51 return 1; 52 } 53 fclose(file); 54 55 // Parse the wat into the binary wasm format 56 wasm_byte_vec_t wasm; 57 error = wasmtime_wat2wasm(wat.data, wat.size, &wasm); 58 if (error != NULL) 59 exit_with_error("failed to parse wat", error, NULL); 60 wasm_byte_vec_delete(&wat); 61 62 // Compile and instantiate our module 63 wasmtime_module_t *module = NULL; 64 error = wasmtime_module_new(engine, (uint8_t *)wasm.data, wasm.size, &module); 65 if (module == NULL) 66 exit_with_error("failed to compile module", error, NULL); 67 wasm_byte_vec_delete(&wasm); 68 69 wasm_trap_t *trap = NULL; 70 wasmtime_instance_t instance; 71 error = wasmtime_instance_new(context, module, NULL, 0, &instance, &trap); 72 if (error != NULL || trap != NULL) 73 exit_with_error("failed to instantiate", error, trap); 74 75 // Lookup our `fibonacci` export function 76 wasmtime_extern_t fib; 77 bool ok = wasmtime_instance_export_get(context, &instance, "fibonacci", 78 strlen("fibonacci"), &fib); 79 assert(ok); 80 assert(fib.kind == WASMTIME_EXTERN_FUNC); 81 82 // Call it repeatedly until it fails 83 for (int n = 1;; n++) { 84 uint64_t fuel_before; 85 wasmtime_context_get_fuel(context, &fuel_before); 86 wasmtime_val_t params[1]; 87 params[0].kind = WASMTIME_I32; 88 params[0].of.i32 = n; 89 wasmtime_val_t results[1]; 90 error = 91 wasmtime_func_call(context, &fib.of.func, params, 1, results, 1, &trap); 92 if (error != NULL || trap != NULL) { 93 if (trap != NULL) { 94 wasmtime_trap_code_t code; 95 assert(wasmtime_trap_code(trap, &code)); 96 assert(code == WASMTIME_TRAP_CODE_OUT_OF_FUEL); 97 wasm_trap_delete(trap); 98 } 99 if (error != NULL) 100 wasmtime_error_delete(error); 101 printf("Exhausted fuel computing fib(%d)\n", n); 102 break; 103 } 104 105 uint64_t fuel_after; 106 wasmtime_context_get_fuel(context, &fuel_after); 107 assert(results[0].kind == WASMTIME_I32); 108 printf("fib(%d) = %d [consumed %lu fuel]\n", n, results[0].of.i32, 109 fuel_after - fuel_before); 110 111 error = wasmtime_context_set_fuel(context, 10000); 112 if (error != NULL) 113 exit_with_error("failed to set fuel", error, NULL); 114 } 115 116 // Clean up after ourselves at this point 117 wasmtime_module_delete(module); 118 wasmtime_store_delete(store); 119 wasm_engine_delete(engine); 120 return 0; 121 } 122 123 static void exit_with_error(const char *message, wasmtime_error_t *error, 124 wasm_trap_t *trap) { 125 fprintf(stderr, "error: %s\n", message); 126 wasm_byte_vec_t error_message; 127 if (error != NULL) { 128 wasmtime_error_message(error, &error_message); 129 } else { 130 wasm_trap_message(trap, &error_message); 131 } 132 fprintf(stderr, "%.*s\n", (int)error_message.size, error_message.data); 133 wasm_byte_vec_delete(&error_message); 134 exit(1); 135 } 136