1 /*
2 Example of instantiating a WebAssembly which uses WASI imports.
3
4 You can compile and run this example on Linux with:
5
6 cargo build --release -p wasmtime
7 cc examples/wasi.c \
8 -I crates/c-api/include \
9 -I crates/c-api/wasm-c-api/include \
10 target/release/libwasmtime.a \
11 -lpthread -ldl -lm \
12 -o wasi
13 ./wasi
14
15 Note that on Windows and macOS the command will be similar, but you'll need
16 to tweak the `-lpthread` and such annotations.
17 */
18
19 #include <assert.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <wasm.h>
23 #include <wasi.h>
24 #include <wasmtime.h>
25
26 #define MIN(a, b) ((a) < (b) ? (a) : (b))
27
28 static void exit_with_error(const char *message, wasmtime_error_t *error, wasm_trap_t *trap);
29
main()30 int main() {
31 int ret = 0;
32 // Set up our context
33 wasm_engine_t *engine = wasm_engine_new();
34 assert(engine != NULL);
35 wasm_store_t *store = wasm_store_new(engine);
36 assert(store != NULL);
37
38 wasm_byte_vec_t wasm;
39 // Load our input file to parse it next
40 FILE* file = fopen("target/wasm32-wasi/debug/wasi.wasm", "rb");
41 if (!file) {
42 printf("> Error loading file!\n");
43 exit(1);
44 }
45 fseek(file, 0L, SEEK_END);
46 size_t file_size = ftell(file);
47 wasm_byte_vec_new_uninitialized(&wasm, file_size);
48 fseek(file, 0L, SEEK_SET);
49 if (fread(wasm.data, file_size, 1, file) != 1) {
50 printf("> Error loading module!\n");
51 exit(1);
52 }
53 fclose(file);
54
55 // Compile our modules
56 wasm_module_t *module = NULL;
57 wasmtime_error_t *error = wasmtime_module_new(store, &wasm, &module);
58 if (!module)
59 exit_with_error("failed to compile module", error, NULL);
60 wasm_byte_vec_delete(&wasm);
61
62 // Instantiate wasi
63 wasi_config_t *wasi_config = wasi_config_new();
64 assert(wasi_config);
65 wasi_config_inherit_argv(wasi_config);
66 wasi_config_inherit_env(wasi_config);
67 wasi_config_inherit_stdin(wasi_config);
68 wasi_config_inherit_stdout(wasi_config);
69 wasi_config_inherit_stderr(wasi_config);
70 wasm_trap_t *trap = NULL;
71 wasi_instance_t *wasi = wasi_instance_new(store, "wasi_snapshot_preview1", wasi_config, &trap);
72 if (wasi == NULL)
73 exit_with_error("failed to instantiate WASI", NULL, trap);
74
75 wasmtime_linker_t *linker = wasmtime_linker_new(store);
76 error = wasmtime_linker_define_wasi(linker, wasi);
77 if (error != NULL)
78 exit_with_error("failed to link wasi", error, NULL);
79
80 // Instantiate the module
81 wasm_name_t empty;
82 wasm_name_new_from_string(&empty, "");
83 wasm_instance_t *instance = NULL;
84 error = wasmtime_linker_module(linker, &empty, module);
85 if (error != NULL)
86 exit_with_error("failed to instantiate module", error, NULL);
87
88 // Run it.
89 wasm_func_t* func;
90 wasmtime_linker_get_default(linker, &empty, &func);
91 if (error != NULL)
92 exit_with_error("failed to locate default export for module", error, NULL);
93 error = wasmtime_func_call(func, NULL, 0, NULL, 0, &trap);
94 if (error != NULL)
95 exit_with_error("error calling default export", error, trap);
96
97 // Clean up after ourselves at this point
98 wasm_name_delete(&empty);
99 wasm_module_delete(module);
100 wasm_store_delete(store);
101 wasm_engine_delete(engine);
102 return 0;
103 }
104
exit_with_error(const char * message,wasmtime_error_t * error,wasm_trap_t * trap)105 static void exit_with_error(const char *message, wasmtime_error_t *error, wasm_trap_t *trap) {
106 fprintf(stderr, "error: %s\n", message);
107 wasm_byte_vec_t error_message;
108 if (error != NULL) {
109 wasmtime_error_message(error, &error_message);
110 wasmtime_error_delete(error);
111 } else {
112 wasm_trap_message(trap, &error_message);
113 wasm_trap_delete(trap);
114 }
115 fprintf(stderr, "%.*s\n", (int) error_message.size, error_message.data);
116 wasm_byte_vec_delete(&error_message);
117 exit(1);
118 }
119