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