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/multi.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 multi 14 ./multi 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. 18 19 You can also build using cmake: 20 21 mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-multi 22 23 Also note that this example was taken from 24 https://github.com/WebAssembly/wasm-c-api/blob/master/example/multi.c 25 originally 26 */ 27 28 #include <inttypes.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <wasm.h> 33 #include <wasmtime.h> 34 35 static void exit_with_error(const char *message, wasmtime_error_t *error, 36 wasm_trap_t *trap); 37 38 // A function to be called from Wasm code. 39 wasm_trap_t *callback(void *env, wasmtime_caller_t *caller, 40 const wasmtime_val_t *args, size_t nargs, 41 wasmtime_val_t *results, size_t nresults) { 42 printf("Calling back...\n"); 43 printf("> %" PRIu32 " %" PRIu64 "\n", args[0].of.i32, args[1].of.i64); 44 printf("\n"); 45 46 results[0] = args[1]; 47 results[1] = args[0]; 48 return NULL; 49 } 50 51 // A function closure. 52 wasm_trap_t *closure_callback(void *env, wasmtime_caller_t *caller, 53 const wasmtime_val_t *args, size_t nargs, 54 wasmtime_val_t *results, size_t nresults) { 55 int i = *(int *)env; 56 printf("Calling back closure...\n"); 57 printf("> %d\n", i); 58 59 results[0].kind = WASMTIME_I32; 60 results[0].of.i32 = (int32_t)i; 61 return NULL; 62 } 63 64 int main(int argc, const char *argv[]) { 65 // Initialize. 66 printf("Initializing...\n"); 67 wasm_engine_t *engine = wasm_engine_new(); 68 wasmtime_store_t *store = wasmtime_store_new(engine, NULL, NULL); 69 wasmtime_context_t *context = wasmtime_store_context(store); 70 71 // Load our input file to parse it next 72 FILE *file = fopen("examples/multi.wat", "r"); 73 if (!file) { 74 printf("> Error loading file!\n"); 75 return 1; 76 } 77 fseek(file, 0L, SEEK_END); 78 size_t file_size = ftell(file); 79 fseek(file, 0L, SEEK_SET); 80 wasm_byte_vec_t wat; 81 wasm_byte_vec_new_uninitialized(&wat, file_size); 82 if (fread(wat.data, file_size, 1, file) != 1) { 83 printf("> Error loading module!\n"); 84 return 1; 85 } 86 fclose(file); 87 88 // Parse the wat into the binary wasm format 89 wasm_byte_vec_t binary; 90 wasmtime_error_t *error = wasmtime_wat2wasm(wat.data, wat.size, &binary); 91 if (error != NULL) 92 exit_with_error("failed to parse wat", error, NULL); 93 wasm_byte_vec_delete(&wat); 94 95 // Compile. 96 printf("Compiling module...\n"); 97 wasmtime_module_t *module = NULL; 98 error = 99 wasmtime_module_new(engine, (uint8_t *)binary.data, binary.size, &module); 100 if (error) 101 exit_with_error("failed to compile module", error, NULL); 102 wasm_byte_vec_delete(&binary); 103 104 // Create external print functions. 105 printf("Creating callback...\n"); 106 wasm_functype_t *callback_type = 107 wasm_functype_new_2_2(wasm_valtype_new_i32(), wasm_valtype_new_i64(), 108 wasm_valtype_new_i64(), wasm_valtype_new_i32()); 109 wasmtime_func_t callback_func; 110 wasmtime_func_new(context, callback_type, callback, NULL, NULL, 111 &callback_func); 112 wasm_functype_delete(callback_type); 113 114 // Instantiate. 115 printf("Instantiating module...\n"); 116 wasmtime_extern_t imports[1]; 117 imports[0].kind = WASMTIME_EXTERN_FUNC; 118 imports[0].of.func = callback_func; 119 wasmtime_instance_t instance; 120 wasm_trap_t *trap = NULL; 121 error = wasmtime_instance_new(context, module, imports, 1, &instance, &trap); 122 if (error != NULL || trap != NULL) 123 exit_with_error("failed to instantiate", error, trap); 124 wasmtime_module_delete(module); 125 126 // Extract export. 127 printf("Extracting export...\n"); 128 wasmtime_extern_t run; 129 bool ok = wasmtime_instance_export_get(context, &instance, "g", 1, &run); 130 assert(ok); 131 assert(run.kind == WASMTIME_EXTERN_FUNC); 132 133 // Call. 134 printf("Calling export...\n"); 135 wasmtime_val_t args[2]; 136 args[0].kind = WASMTIME_I32; 137 args[0].of.i32 = 1; 138 args[1].kind = WASMTIME_I64; 139 args[1].of.i64 = 2; 140 wasmtime_val_t results[2]; 141 error = wasmtime_func_call(context, &run.of.func, args, 2, results, 2, &trap); 142 if (error != NULL || trap != NULL) 143 exit_with_error("failed to call run", error, trap); 144 145 // Print result. 146 printf("Printing result...\n"); 147 printf("> %" PRIu64 " %" PRIu32 "\n", results[0].of.i64, results[1].of.i32); 148 149 assert(results[0].kind == WASMTIME_I64); 150 assert(results[0].of.i64 == 2); 151 assert(results[1].kind == WASMTIME_I32); 152 assert(results[1].of.i32 == 1); 153 154 // Shut down. 155 printf("Shutting down...\n"); 156 wasmtime_store_delete(store); 157 wasm_engine_delete(engine); 158 159 // All done. 160 printf("Done.\n"); 161 return 0; 162 } 163 164 static void exit_with_error(const char *message, wasmtime_error_t *error, 165 wasm_trap_t *trap) { 166 fprintf(stderr, "error: %s\n", message); 167 wasm_byte_vec_t error_message; 168 if (error != NULL) { 169 wasmtime_error_message(error, &error_message); 170 wasmtime_error_delete(error); 171 } else { 172 wasm_trap_message(trap, &error_message); 173 wasm_trap_delete(trap); 174 } 175 fprintf(stderr, "%.*s\n", (int)error_message.size, error_message.data); 176 wasm_byte_vec_delete(&error_message); 177 exit(1); 178 } 179