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