1 /* 2 Example of instantiating of the WebAssembly module and invoking its exported 3 function. 4 5 You can compile and run this example on Linux with: 6 7 cargo build --release -p wasmtime-c-api 8 cc examples/interrupt.c \ 9 -I crates/c-api/include \ 10 -I crates/c-api/wasm-c-api/include \ 11 target/release/libwasmtime.a \ 12 -lpthread -ldl -lm \ 13 -o interrupt 14 ./interrupt 15 16 Note that on Windows and macOS the command will be similar, but you'll need 17 to tweak the `-lpthread` and such annotations as well as the name of the 18 `libwasmtime.a` file on Windows. 19 */ 20 21 #include <assert.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <wasm.h> 25 #include <wasmtime.h> 26 27 #ifdef _WIN32 28 static void spawn_interrupt(wasm_engine_t *engine) { 29 wasmtime_engine_increment_epoch(engine); 30 } 31 #else 32 #include <pthread.h> 33 #include <time.h> 34 35 static void* helper(void *_engine) { 36 wasm_engine_t *engine = _engine; 37 struct timespec sleep_dur; 38 sleep_dur.tv_sec = 1; 39 sleep_dur.tv_nsec = 0; 40 nanosleep(&sleep_dur, NULL); 41 printf("Sending an interrupt\n"); 42 wasmtime_engine_increment_epoch(engine); 43 return 0; 44 } 45 46 static void spawn_interrupt(wasm_engine_t *engine) { 47 pthread_t child; 48 int rc = pthread_create(&child, NULL, helper, engine); 49 assert(rc == 0); 50 } 51 #endif 52 53 static void exit_with_error(const char *message, wasmtime_error_t *error, wasm_trap_t *trap); 54 55 int main() { 56 // Create a `wasm_store_t` with interrupts enabled 57 wasm_config_t *config = wasm_config_new(); 58 assert(config != NULL); 59 wasmtime_config_epoch_interruption_set(config, true); 60 wasm_engine_t *engine = wasm_engine_new_with_config(config); 61 assert(engine != NULL); 62 wasmtime_store_t *store = wasmtime_store_new(engine, NULL, NULL); 63 assert(store != NULL); 64 wasmtime_context_t *context = wasmtime_store_context(store); 65 66 // Configure the epoch deadline after which WebAssembly code will trap. 67 wasmtime_context_set_epoch_deadline(context, 1); 68 69 // Read our input file, which in this case is a wasm text file. 70 FILE* file = fopen("examples/interrupt.wat", "r"); 71 assert(file != NULL); 72 fseek(file, 0L, SEEK_END); 73 size_t file_size = ftell(file); 74 fseek(file, 0L, SEEK_SET); 75 wasm_byte_vec_t wat; 76 wasm_byte_vec_new_uninitialized(&wat, file_size); 77 assert(fread(wat.data, file_size, 1, file) == 1); 78 fclose(file); 79 80 // Parse the wat into the binary wasm format 81 wasm_byte_vec_t wasm; 82 wasmtime_error_t *error = wasmtime_wat2wasm(wat.data, wat.size, &wasm); 83 if (error != NULL) 84 exit_with_error("failed to parse wat", error, NULL); 85 wasm_byte_vec_delete(&wat); 86 87 // Now that we've got our binary webassembly we can compile our module. 88 wasmtime_module_t *module = NULL; 89 error = wasmtime_module_new(engine, (uint8_t*) wasm.data, wasm.size, &module); 90 wasm_byte_vec_delete(&wasm); 91 if (error != NULL) 92 exit_with_error("failed to compile module", error, NULL); 93 94 wasm_trap_t *trap = NULL; 95 wasmtime_instance_t instance; 96 error = wasmtime_instance_new(context, module, NULL, 0, &instance, &trap); 97 if (error != NULL || trap != NULL) 98 exit_with_error("failed to instantiate", error, trap); 99 wasmtime_module_delete(module); 100 101 // Lookup our `run` export function 102 wasmtime_extern_t run; 103 bool ok = wasmtime_instance_export_get(context, &instance, "run", 3, &run); 104 assert(ok); 105 assert(run.kind == WASMTIME_EXTERN_FUNC); 106 107 // Spawn a thread to send us an interrupt after a period of time. 108 spawn_interrupt(engine); 109 110 // And call it! 111 printf("Entering infinite loop...\n"); 112 error = wasmtime_func_call(context, &run.of.func, NULL, 0, NULL, 0, &trap); 113 assert(error == NULL); 114 assert(trap != NULL); 115 printf("Got a trap!...\n"); 116 117 wasmtime_store_delete(store); 118 wasm_engine_delete(engine); 119 return 0; 120 } 121 122 static void exit_with_error(const char *message, wasmtime_error_t *error, wasm_trap_t *trap) { 123 fprintf(stderr, "error: %s\n", message); 124 wasm_byte_vec_t error_message; 125 if (error != NULL) { 126 wasmtime_error_message(error, &error_message); 127 wasmtime_error_delete(error); 128 } else { 129 wasm_trap_message(trap, &error_message); 130 wasm_trap_delete(trap); 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