Skip to content

Commit 3a5dda5

Browse files
authored
Split final C++ items out of wasmtime.hh (#10692)
* Split final C++ items out of `wasmtime.hh` Now `wasmtime.hh` is just an "amalgamation" header to include everything, yay! * Format files * Try to fix MSVC
1 parent 63df06b commit 3a5dda5

File tree

13 files changed

+516
-445
lines changed

13 files changed

+516
-445
lines changed

crates/c-api/include/wasmtime.hh

Lines changed: 6 additions & 325 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
* [Wasmtime](https://github.com/bytecodealliance/wasmtime). Support for the
44
* C++ API is exclusively built on the [C API of
55
* Wasmtime](https://docs.wasmtime.dev/c-api/), so the C++ support for this is
6-
* simply a single header file. To use this header file, though, it must be
7-
* combined with the header and binary of Wasmtime's C API. Note, though, that
8-
* while this header is built on top of the `wasmtime.h` header file you should
9-
* only need to use the contents of this header file to interact with Wasmtime.
6+
* just a set of header files. Like the C API the C++ API is split into
7+
* separate headers to be included on an as-needed basis. Types shouldn't
8+
* need to use the C API, but if something is missing please feel free to file
9+
* an issue.
1010
*
1111
* Examples can be [found
1212
* online](https://github.com/bytecodealliance/wasmtime/tree/main/examples)
@@ -30,25 +30,14 @@
3030
#ifndef WASMTIME_HH
3131
#define WASMTIME_HH
3232

33-
#include <any>
34-
#include <array>
35-
#include <cstdio>
36-
#include <initializer_list>
37-
#include <iosfwd>
38-
#include <limits>
39-
#include <memory>
40-
#include <optional>
41-
#include <ostream>
42-
#include <variant>
43-
#include <vector>
44-
45-
#include <wasmtime.h>
4633
#include <wasmtime/config.hh>
4734
#include <wasmtime/engine.hh>
4835
#include <wasmtime/error.hh>
4936
#include <wasmtime/extern.hh>
5037
#include <wasmtime/func.hh>
5138
#include <wasmtime/global.hh>
39+
#include <wasmtime/instance.hh>
40+
#include <wasmtime/linker.hh>
5241
#include <wasmtime/memory.hh>
5342
#include <wasmtime/module.hh>
5443
#include <wasmtime/store.hh>
@@ -58,312 +47,4 @@
5847
#include <wasmtime/val.hh>
5948
#include <wasmtime/wasi.hh>
6049

61-
namespace wasmtime {
62-
63-
/**
64-
* \brief A WebAssembly instance.
65-
*
66-
* This class represents a WebAssembly instance, created by instantiating a
67-
* module. An instance is the collection of items exported by the module, which
68-
* can be accessed through the `Store` that owns the instance.
69-
*
70-
* Note that this type does not itself own any resources. It points to resources
71-
* owned within a `Store` and the `Store` must be passed in as the first
72-
* argument to the functions defined on `Instance`. Note that if the wrong
73-
* `Store` is passed in then the process will be aborted.
74-
*/
75-
class Instance {
76-
friend class Linker;
77-
friend class Caller;
78-
79-
wasmtime_instance_t instance;
80-
81-
static Extern cvt(wasmtime_extern_t &e) {
82-
switch (e.kind) {
83-
case WASMTIME_EXTERN_FUNC:
84-
return Func(e.of.func);
85-
case WASMTIME_EXTERN_GLOBAL:
86-
return Global(e.of.global);
87-
case WASMTIME_EXTERN_MEMORY:
88-
return Memory(e.of.memory);
89-
case WASMTIME_EXTERN_TABLE:
90-
return Table(e.of.table);
91-
}
92-
std::abort();
93-
}
94-
95-
static void cvt(const Extern &e, wasmtime_extern_t &raw) {
96-
if (const auto *func = std::get_if<Func>(&e)) {
97-
raw.kind = WASMTIME_EXTERN_FUNC;
98-
raw.of.func = func->func;
99-
} else if (const auto *global = std::get_if<Global>(&e)) {
100-
raw.kind = WASMTIME_EXTERN_GLOBAL;
101-
raw.of.global = global->global;
102-
} else if (const auto *table = std::get_if<Table>(&e)) {
103-
raw.kind = WASMTIME_EXTERN_TABLE;
104-
raw.of.table = table->table;
105-
} else if (const auto *memory = std::get_if<Memory>(&e)) {
106-
raw.kind = WASMTIME_EXTERN_MEMORY;
107-
raw.of.memory = memory->memory;
108-
} else {
109-
std::abort();
110-
}
111-
}
112-
113-
public:
114-
/// Creates a new instance from the raw underlying C API representation.
115-
Instance(wasmtime_instance_t instance) : instance(instance) {}
116-
117-
/**
118-
* \brief Instantiates the module `m` with the provided `imports`
119-
*
120-
* \param cx the store in which to instantiate the provided module
121-
* \param m the module to instantiate
122-
* \param imports the list of imports to use to instantiate the module
123-
*
124-
* This `imports` parameter is expected to line up 1:1 with the imports
125-
* required by the `m`. The type of `m` can be inspected to determine in which
126-
* order to provide the imports. Note that this is a relatively low-level API
127-
* and it's generally recommended to use `Linker` instead for name-based
128-
* instantiation.
129-
*
130-
* This function can return an error if any of the `imports` have the wrong
131-
* type, or if the wrong number of `imports` is provided.
132-
*/
133-
static TrapResult<Instance> create(Store::Context cx, const Module &m,
134-
const std::vector<Extern> &imports) {
135-
std::vector<wasmtime_extern_t> raw_imports;
136-
for (const auto &item : imports) {
137-
raw_imports.push_back(wasmtime_extern_t{});
138-
auto &last = raw_imports.back();
139-
Instance::cvt(item, last);
140-
}
141-
wasmtime_instance_t instance;
142-
wasm_trap_t *trap = nullptr;
143-
auto *error = wasmtime_instance_new(cx.ptr, m.ptr.get(), raw_imports.data(),
144-
raw_imports.size(), &instance, &trap);
145-
if (error != nullptr) {
146-
return TrapError(Error(error));
147-
}
148-
if (trap != nullptr) {
149-
return TrapError(Trap(trap));
150-
}
151-
return Instance(instance);
152-
}
153-
154-
/**
155-
* \brief Load an instance's export by name.
156-
*
157-
* This function will look for an export named `name` on this instance and, if
158-
* found, return it as an `Extern`.
159-
*/
160-
std::optional<Extern> get(Store::Context cx, std::string_view name) {
161-
wasmtime_extern_t e;
162-
if (!wasmtime_instance_export_get(cx.ptr, &instance, name.data(),
163-
name.size(), &e)) {
164-
return std::nullopt;
165-
}
166-
return Instance::cvt(e);
167-
}
168-
169-
/**
170-
* \brief Load an instance's export by index.
171-
*
172-
* This function will look for the `idx`th export of this instance. This will
173-
* return both the name of the export as well as the exported item itself.
174-
*/
175-
std::optional<std::pair<std::string_view, Extern>> get(Store::Context cx,
176-
size_t idx) {
177-
wasmtime_extern_t e;
178-
// I'm not sure why clang-tidy thinks this is using va_list or anything
179-
// related to that...
180-
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
181-
char *name = nullptr;
182-
size_t len = 0;
183-
if (!wasmtime_instance_export_nth(cx.ptr, &instance, idx, &name, &len,
184-
&e)) {
185-
return std::nullopt;
186-
}
187-
std::string_view n(name, len);
188-
return std::pair(n, Instance::cvt(e));
189-
}
190-
};
191-
192-
inline std::optional<Extern> Caller::get_export(std::string_view name) {
193-
wasmtime_extern_t item;
194-
if (wasmtime_caller_export_get(ptr, name.data(), name.size(), &item)) {
195-
return Instance::cvt(item);
196-
}
197-
return std::nullopt;
198-
}
199-
200-
/**
201-
* \brief Helper class for linking modules together with name-based resolution.
202-
*
203-
* This class is used for easily instantiating `Module`s by defining names into
204-
* the linker and performing name-based resolution during instantiation. A
205-
* `Linker` can also be used to link in WASI functions to instantiate a module.
206-
*/
207-
class Linker {
208-
struct deleter {
209-
void operator()(wasmtime_linker_t *p) const { wasmtime_linker_delete(p); }
210-
};
211-
212-
std::unique_ptr<wasmtime_linker_t, deleter> ptr;
213-
214-
public:
215-
/// Creates a new linker which will instantiate in the given engine.
216-
explicit Linker(Engine &engine)
217-
: ptr(wasmtime_linker_new(engine.ptr.get())) {}
218-
219-
/// Configures whether shadowing previous names is allowed or not.
220-
///
221-
/// By default shadowing is not allowed.
222-
void allow_shadowing(bool allow) {
223-
wasmtime_linker_allow_shadowing(ptr.get(), allow);
224-
}
225-
226-
/// Defines the provided item into this linker with the given name.
227-
Result<std::monostate> define(Store::Context cx, std::string_view module,
228-
std::string_view name, const Extern &item) {
229-
wasmtime_extern_t raw;
230-
Instance::cvt(item, raw);
231-
auto *error =
232-
wasmtime_linker_define(ptr.get(), cx.ptr, module.data(), module.size(),
233-
name.data(), name.size(), &raw);
234-
if (error != nullptr) {
235-
return Error(error);
236-
}
237-
return std::monostate();
238-
}
239-
240-
/// Defines WASI functions within this linker.
241-
///
242-
/// Note that `Store::Context::set_wasi` must also be used for instantiated
243-
/// modules to have access to configured WASI state.
244-
Result<std::monostate> define_wasi() {
245-
auto *error = wasmtime_linker_define_wasi(ptr.get());
246-
if (error != nullptr) {
247-
return Error(error);
248-
}
249-
return std::monostate();
250-
}
251-
252-
/// Defines all exports of the `instance` provided in this linker with the
253-
/// given module name of `name`.
254-
Result<std::monostate>
255-
define_instance(Store::Context cx, std::string_view name, Instance instance) {
256-
auto *error = wasmtime_linker_define_instance(
257-
ptr.get(), cx.ptr, name.data(), name.size(), &instance.instance);
258-
if (error != nullptr) {
259-
return Error(error);
260-
}
261-
return std::monostate();
262-
}
263-
264-
/// Instantiates the module `m` provided within the store `cx` using the items
265-
/// defined within this linker.
266-
TrapResult<Instance> instantiate(Store::Context cx, const Module &m) {
267-
wasmtime_instance_t instance;
268-
wasm_trap_t *trap = nullptr;
269-
auto *error = wasmtime_linker_instantiate(ptr.get(), cx.ptr, m.ptr.get(),
270-
&instance, &trap);
271-
if (error != nullptr) {
272-
return TrapError(Error(error));
273-
}
274-
if (trap != nullptr) {
275-
return TrapError(Trap(trap));
276-
}
277-
return Instance(instance);
278-
}
279-
280-
/// Defines instantiations of the module `m` within this linker under the
281-
/// given `name`.
282-
Result<std::monostate> module(Store::Context cx, std::string_view name,
283-
const Module &m) {
284-
auto *error = wasmtime_linker_module(ptr.get(), cx.ptr, name.data(),
285-
name.size(), m.ptr.get());
286-
if (error != nullptr) {
287-
return Error(error);
288-
}
289-
return std::monostate();
290-
}
291-
292-
/// Attempts to load the specified named item from this linker, returning
293-
/// `std::nullopt` if it was not defined.
294-
[[nodiscard]] std::optional<Extern>
295-
get(Store::Context cx, std::string_view module, std::string_view name) {
296-
wasmtime_extern_t item;
297-
if (wasmtime_linker_get(ptr.get(), cx.ptr, module.data(), module.size(),
298-
name.data(), name.size(), &item)) {
299-
return Instance::cvt(item);
300-
}
301-
return std::nullopt;
302-
}
303-
304-
/// Defines a new function in this linker in the style of the `Func`
305-
/// constructor.
306-
template <typename F,
307-
std::enable_if_t<
308-
std::is_invocable_r_v<Result<std::monostate, Trap>, F, Caller,
309-
Span<const Val>, Span<Val>>,
310-
bool> = true>
311-
Result<std::monostate> func_new(std::string_view module,
312-
std::string_view name, const FuncType &ty,
313-
F &&f) {
314-
315-
auto *error = wasmtime_linker_define_func(
316-
ptr.get(), module.data(), module.length(), name.data(), name.length(),
317-
ty.ptr.get(), Func::raw_callback<std::remove_reference_t<F>>,
318-
std::make_unique<std::remove_reference_t<F>>(std::forward<F>(f))
319-
.release(),
320-
Func::raw_finalize<std::remove_reference_t<F>>);
321-
322-
if (error != nullptr) {
323-
return Error(error);
324-
}
325-
326-
return std::monostate();
327-
}
328-
329-
/// Defines a new function in this linker in the style of the `Func::wrap`
330-
/// constructor.
331-
template <typename F,
332-
std::enable_if_t<WasmHostFunc<F>::Params::valid, bool> = true,
333-
std::enable_if_t<WasmHostFunc<F>::Results::valid, bool> = true>
334-
Result<std::monostate> func_wrap(std::string_view module,
335-
std::string_view name, F &&f) {
336-
using HostFunc = WasmHostFunc<F>;
337-
auto params = HostFunc::Params::types();
338-
auto results = HostFunc::Results::types();
339-
auto ty = FuncType::from_iters(params, results);
340-
auto *error = wasmtime_linker_define_func_unchecked(
341-
ptr.get(), module.data(), module.length(), name.data(), name.length(),
342-
ty.ptr.get(), Func::raw_callback_unchecked<std::remove_reference_t<F>>,
343-
std::make_unique<std::remove_reference_t<F>>(std::forward<F>(f))
344-
.release(),
345-
Func::raw_finalize<std::remove_reference_t<F>>);
346-
347-
if (error != nullptr) {
348-
return Error(error);
349-
}
350-
351-
return std::monostate();
352-
}
353-
354-
/// Loads the "default" function, according to WASI commands and reactors, of
355-
/// the module named `name` in this linker.
356-
Result<Func> get_default(Store::Context cx, std::string_view name) {
357-
wasmtime_func_t item;
358-
auto *error = wasmtime_linker_get_default(ptr.get(), cx.ptr, name.data(),
359-
name.size(), &item);
360-
if (error != nullptr) {
361-
return Error(error);
362-
}
363-
return Func(item);
364-
}
365-
};
366-
367-
} // namespace wasmtime
368-
36950
#endif // WASMTIME_HH

0 commit comments

Comments
 (0)