13c51d3adSAlex Crichton /*
23c51d3adSAlex Crichton Example of instantiating of the WebAssembly module and invoking its exported
33c51d3adSAlex Crichton function.
43c51d3adSAlex Crichton
5*57ba95e9SMasashi Yoshimura You can build using cmake:
62ba3025eSTheGreatRambler
72ba3025eSTheGreatRambler mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-gcd
83c51d3adSAlex Crichton */
93c51d3adSAlex Crichton
103c51d3adSAlex Crichton #include <assert.h>
113c51d3adSAlex Crichton #include <stdio.h>
123c51d3adSAlex Crichton #include <stdlib.h>
133c51d3adSAlex Crichton #include <wasm.h>
143c51d3adSAlex Crichton #include <wasmtime.h>
153c51d3adSAlex Crichton
16f8fee938STyler Rockwood static void exit_with_error(const char *message, wasmtime_error_t *error,
17f8fee938STyler Rockwood wasm_trap_t *trap);
183c51d3adSAlex Crichton
main()193c51d3adSAlex Crichton int main() {
203c51d3adSAlex Crichton int ret = 0;
213c51d3adSAlex Crichton // Set up our context
223c51d3adSAlex Crichton wasm_engine_t *engine = wasm_engine_new();
233c51d3adSAlex Crichton assert(engine != NULL);
247a1b7cdfSAlex Crichton wasmtime_store_t *store = wasmtime_store_new(engine, NULL, NULL);
253c51d3adSAlex Crichton assert(store != NULL);
267a1b7cdfSAlex Crichton wasmtime_context_t *context = wasmtime_store_context(store);
273c51d3adSAlex Crichton
283c51d3adSAlex Crichton // Load our input file to parse it next
293c51d3adSAlex Crichton FILE *file = fopen("examples/gcd.wat", "r");
303c51d3adSAlex Crichton if (!file) {
313c51d3adSAlex Crichton printf("> Error loading file!\n");
323c51d3adSAlex Crichton return 1;
333c51d3adSAlex Crichton }
343c51d3adSAlex Crichton fseek(file, 0L, SEEK_END);
353c51d3adSAlex Crichton size_t file_size = ftell(file);
363c51d3adSAlex Crichton fseek(file, 0L, SEEK_SET);
373c51d3adSAlex Crichton wasm_byte_vec_t wat;
383c51d3adSAlex Crichton wasm_byte_vec_new_uninitialized(&wat, file_size);
393c51d3adSAlex Crichton if (fread(wat.data, file_size, 1, file) != 1) {
403c51d3adSAlex Crichton printf("> Error loading module!\n");
413c51d3adSAlex Crichton return 1;
423c51d3adSAlex Crichton }
433c51d3adSAlex Crichton fclose(file);
443c51d3adSAlex Crichton
453c51d3adSAlex Crichton // Parse the wat into the binary wasm format
46bd374fd6SAlex Crichton wasm_byte_vec_t wasm;
477a1b7cdfSAlex Crichton wasmtime_error_t *error = wasmtime_wat2wasm(wat.data, wat.size, &wasm);
48bd374fd6SAlex Crichton if (error != NULL)
49bd374fd6SAlex Crichton exit_with_error("failed to parse wat", error, NULL);
503c51d3adSAlex Crichton wasm_byte_vec_delete(&wat);
513c51d3adSAlex Crichton
523c51d3adSAlex Crichton // Compile and instantiate our module
537a1b7cdfSAlex Crichton wasmtime_module_t *module = NULL;
547a1b7cdfSAlex Crichton error = wasmtime_module_new(engine, (uint8_t *)wasm.data, wasm.size, &module);
55bd374fd6SAlex Crichton if (module == NULL)
56bd374fd6SAlex Crichton exit_with_error("failed to compile module", error, NULL);
573c51d3adSAlex Crichton wasm_byte_vec_delete(&wasm);
587a1b7cdfSAlex Crichton
593c51d3adSAlex Crichton wasm_trap_t *trap = NULL;
607a1b7cdfSAlex Crichton wasmtime_instance_t instance;
617a1b7cdfSAlex Crichton error = wasmtime_instance_new(context, module, NULL, 0, &instance, &trap);
627a1b7cdfSAlex Crichton if (error != NULL || trap != NULL)
63bd374fd6SAlex Crichton exit_with_error("failed to instantiate", error, trap);
643c51d3adSAlex Crichton
653c51d3adSAlex Crichton // Lookup our `gcd` export function
667a1b7cdfSAlex Crichton wasmtime_extern_t gcd;
677a1b7cdfSAlex Crichton bool ok = wasmtime_instance_export_get(context, &instance, "gcd", 3, &gcd);
687a1b7cdfSAlex Crichton assert(ok);
697a1b7cdfSAlex Crichton assert(gcd.kind == WASMTIME_EXTERN_FUNC);
703c51d3adSAlex Crichton
713c51d3adSAlex Crichton // And call it!
723c51d3adSAlex Crichton int a = 6;
733c51d3adSAlex Crichton int b = 27;
747a1b7cdfSAlex Crichton wasmtime_val_t params[2];
757a1b7cdfSAlex Crichton params[0].kind = WASMTIME_I32;
767a1b7cdfSAlex Crichton params[0].of.i32 = a;
777a1b7cdfSAlex Crichton params[1].kind = WASMTIME_I32;
787a1b7cdfSAlex Crichton params[1].of.i32 = b;
797a1b7cdfSAlex Crichton wasmtime_val_t results[1];
80f8fee938STyler Rockwood error =
81f8fee938STyler Rockwood wasmtime_func_call(context, &gcd.of.func, params, 2, results, 1, &trap);
82bd374fd6SAlex Crichton if (error != NULL || trap != NULL)
83bd374fd6SAlex Crichton exit_with_error("failed to call gcd", error, trap);
847a1b7cdfSAlex Crichton assert(results[0].kind == WASMTIME_I32);
853c51d3adSAlex Crichton
863c51d3adSAlex Crichton printf("gcd(%d, %d) = %d\n", a, b, results[0].of.i32);
873c51d3adSAlex Crichton
883c51d3adSAlex Crichton // Clean up after ourselves at this point
893c51d3adSAlex Crichton ret = 0;
903c51d3adSAlex Crichton
917a1b7cdfSAlex Crichton wasmtime_module_delete(module);
927a1b7cdfSAlex Crichton wasmtime_store_delete(store);
933c51d3adSAlex Crichton wasm_engine_delete(engine);
943c51d3adSAlex Crichton return ret;
953c51d3adSAlex Crichton }
963c51d3adSAlex Crichton
exit_with_error(const char * message,wasmtime_error_t * error,wasm_trap_t * trap)97f8fee938STyler Rockwood static void exit_with_error(const char *message, wasmtime_error_t *error,
98f8fee938STyler Rockwood wasm_trap_t *trap) {
99bd374fd6SAlex Crichton fprintf(stderr, "error: %s\n", message);
100bd374fd6SAlex Crichton wasm_byte_vec_t error_message;
101bd374fd6SAlex Crichton if (error != NULL) {
102bd374fd6SAlex Crichton wasmtime_error_message(error, &error_message);
103bd374fd6SAlex Crichton } else {
104bd374fd6SAlex Crichton wasm_trap_message(trap, &error_message);
105bd374fd6SAlex Crichton }
106bd374fd6SAlex Crichton fprintf(stderr, "%.*s\n", (int)error_message.size, error_message.data);
107bd374fd6SAlex Crichton wasm_byte_vec_delete(&error_message);
108bd374fd6SAlex Crichton exit(1);
1093c51d3adSAlex Crichton }
110