Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/examples/linking.c
3056 views
1
/*
2
Example of compiling, instantiating, and linking two WebAssembly modules
3
together.
4
5
You can build using cmake:
6
7
mkdir build && cd build && cmake .. && cmake --build . --target wasmtime-linking
8
*/
9
10
#include <assert.h>
11
#include <stdio.h>
12
#include <stdlib.h>
13
#include <wasi.h>
14
#include <wasm.h>
15
#include <wasmtime.h>
16
17
#define MIN(a, b) ((a) < (b) ? (a) : (b))
18
19
static void exit_with_error(const char *message, wasmtime_error_t *error,
20
wasm_trap_t *trap);
21
static void read_wat_file(wasm_byte_vec_t *bytes, const char *file);
22
23
int main() {
24
// Set up our context
25
wasm_engine_t *engine = wasm_engine_new();
26
assert(engine != NULL);
27
wasmtime_store_t *store = wasmtime_store_new(engine, NULL, NULL);
28
assert(store != NULL);
29
wasmtime_context_t *context = wasmtime_store_context(store);
30
31
wasm_byte_vec_t linking1_wasm, linking2_wasm;
32
read_wat_file(&linking1_wasm, "examples/linking1.wat");
33
read_wat_file(&linking2_wasm, "examples/linking2.wat");
34
35
// Compile our two modules
36
wasmtime_error_t *error;
37
wasmtime_module_t *linking1_module = NULL;
38
wasmtime_module_t *linking2_module = NULL;
39
error = wasmtime_module_new(engine, (uint8_t *)linking1_wasm.data,
40
linking1_wasm.size, &linking1_module);
41
if (error != NULL)
42
exit_with_error("failed to compile linking1", error, NULL);
43
error = wasmtime_module_new(engine, (uint8_t *)linking2_wasm.data,
44
linking2_wasm.size, &linking2_module);
45
if (error != NULL)
46
exit_with_error("failed to compile linking2", error, NULL);
47
wasm_byte_vec_delete(&linking1_wasm);
48
wasm_byte_vec_delete(&linking2_wasm);
49
50
// Configure WASI and store it within our `wasmtime_store_t`
51
wasi_config_t *wasi_config = wasi_config_new();
52
assert(wasi_config);
53
wasi_config_inherit_argv(wasi_config);
54
wasi_config_inherit_env(wasi_config);
55
wasi_config_inherit_stdin(wasi_config);
56
wasi_config_inherit_stdout(wasi_config);
57
wasi_config_inherit_stderr(wasi_config);
58
wasm_trap_t *trap = NULL;
59
error = wasmtime_context_set_wasi(context, wasi_config);
60
if (error != NULL)
61
exit_with_error("failed to instantiate wasi", NULL, trap);
62
63
// Create our linker which will be linking our modules together, and then add
64
// our WASI instance to it.
65
wasmtime_linker_t *linker = wasmtime_linker_new(engine);
66
error = wasmtime_linker_define_wasi(linker);
67
if (error != NULL)
68
exit_with_error("failed to link wasi", error, NULL);
69
70
// Instantiate `linking2` with our linker.
71
wasmtime_instance_t linking2;
72
error = wasmtime_linker_instantiate(linker, context, linking2_module,
73
&linking2, &trap);
74
if (error != NULL || trap != NULL)
75
exit_with_error("failed to instantiate linking2", error, trap);
76
77
// Register our new `linking2` instance with the linker
78
error = wasmtime_linker_define_instance(linker, context, "linking2",
79
strlen("linking2"), &linking2);
80
if (error != NULL)
81
exit_with_error("failed to link linking2", error, NULL);
82
83
// Instantiate `linking1` with the linker now that `linking2` is defined
84
wasmtime_instance_t linking1;
85
error = wasmtime_linker_instantiate(linker, context, linking1_module,
86
&linking1, &trap);
87
if (error != NULL || trap != NULL)
88
exit_with_error("failed to instantiate linking1", error, trap);
89
90
// Lookup our `run` export function
91
wasmtime_extern_t run;
92
bool ok = wasmtime_instance_export_get(context, &linking1, "run", 3, &run);
93
assert(ok);
94
assert(run.kind == WASMTIME_EXTERN_FUNC);
95
error = wasmtime_func_call(context, &run.of.func, NULL, 0, NULL, 0, &trap);
96
if (error != NULL || trap != NULL)
97
exit_with_error("failed to call run", error, trap);
98
99
// Clean up after ourselves at this point
100
wasmtime_linker_delete(linker);
101
wasmtime_module_delete(linking1_module);
102
wasmtime_module_delete(linking2_module);
103
wasmtime_store_delete(store);
104
wasm_engine_delete(engine);
105
return 0;
106
}
107
108
static void read_wat_file(wasm_byte_vec_t *bytes, const char *filename) {
109
wasm_byte_vec_t wat;
110
// Load our input file to parse it next
111
FILE *file = fopen(filename, "r");
112
if (!file) {
113
printf("> Error loading file!\n");
114
exit(1);
115
}
116
fseek(file, 0L, SEEK_END);
117
size_t file_size = ftell(file);
118
wasm_byte_vec_new_uninitialized(&wat, file_size);
119
fseek(file, 0L, SEEK_SET);
120
if (fread(wat.data, file_size, 1, file) != 1) {
121
printf("> Error loading module!\n");
122
exit(1);
123
}
124
fclose(file);
125
126
// Parse the wat into the binary wasm format
127
wasmtime_error_t *error = wasmtime_wat2wasm(wat.data, wat.size, bytes);
128
if (error != NULL)
129
exit_with_error("failed to parse wat", error, NULL);
130
wasm_byte_vec_delete(&wat);
131
}
132
133
static void exit_with_error(const char *message, wasmtime_error_t *error,
134
wasm_trap_t *trap) {
135
fprintf(stderr, "error: %s\n", message);
136
wasm_byte_vec_t error_message;
137
if (error != NULL) {
138
wasmtime_error_message(error, &error_message);
139
wasmtime_error_delete(error);
140
} else {
141
wasm_trap_message(trap, &error_message);
142
wasm_trap_delete(trap);
143
}
144
fprintf(stderr, "%.*s\n", (int)error_message.size, error_message.data);
145
wasm_byte_vec_delete(&error_message);
146
exit(1);
147
}
148
149