1 /**
2  * \file wasmtime/instance.hh
3  */
4 
5 #ifndef WASMTIME_INSTANCE_HH
6 #define WASMTIME_INSTANCE_HH
7 
8 #include <wasmtime/extern.hh>
9 #include <wasmtime/func.hh>
10 #include <wasmtime/global.hh>
11 #include <wasmtime/instance.h>
12 #include <wasmtime/memory.hh>
13 #include <wasmtime/module.hh>
14 #include <wasmtime/store.hh>
15 #include <wasmtime/table.hh>
16 
17 namespace wasmtime {
18 
19 /**
20  * \brief A WebAssembly instance.
21  *
22  * This class represents a WebAssembly instance, created by instantiating a
23  * module. An instance is the collection of items exported by the module, which
24  * can be accessed through the `Store` that owns the instance.
25  *
26  * Note that this type does not itself own any resources. It points to resources
27  * owned within a `Store` and the `Store` must be passed in as the first
28  * argument to the functions defined on `Instance`. Note that if the wrong
29  * `Store` is passed in then the process will be aborted.
30  */
31 class Instance {
32   friend class Linker;
33   friend class Caller;
34 
35   wasmtime_instance_t instance;
36 
37 public:
38   /// Creates a new instance from the raw underlying C API representation.
39   Instance(wasmtime_instance_t instance) : instance(instance) {}
40 
41   /**
42    * \brief Instantiates the module `m` with the provided `imports`
43    *
44    * \param cx the store in which to instantiate the provided module
45    * \param m the module to instantiate
46    * \param imports the list of imports to use to instantiate the module
47    *
48    * This `imports` parameter is expected to line up 1:1 with the imports
49    * required by the `m`. The type of `m` can be inspected to determine in which
50    * order to provide the imports. Note that this is a relatively low-level API
51    * and it's generally recommended to use `Linker` instead for name-based
52    * instantiation.
53    *
54    * This function can return an error if any of the `imports` have the wrong
55    * type, or if the wrong number of `imports` is provided.
56    */
57   static TrapResult<Instance> create(Store::Context cx, const Module &m,
58                                      const std::vector<Extern> &imports) {
59     std::vector<wasmtime_extern_t> raw_imports;
60     for (const auto &item : imports) {
61       raw_imports.push_back(wasmtime_extern_t{});
62       auto &last = raw_imports.back();
63       detail::cvt_extern(item, last);
64     }
65     wasmtime_instance_t instance;
66     wasm_trap_t *trap = nullptr;
67     auto *error = wasmtime_instance_new(cx.ptr, m.capi(), raw_imports.data(),
68                                         raw_imports.size(), &instance, &trap);
69     if (error != nullptr) {
70       return TrapError(Error(error));
71     }
72     if (trap != nullptr) {
73       return TrapError(Trap(trap));
74     }
75     return Instance(instance);
76   }
77 
78   /**
79    * \brief Load an instance's export by name.
80    *
81    * This function will look for an export named `name` on this instance and, if
82    * found, return it as an `Extern`.
83    */
84   std::optional<Extern> get(Store::Context cx, std::string_view name) {
85     wasmtime_extern_t e;
86     if (!wasmtime_instance_export_get(cx.ptr, &instance, name.data(),
87                                       name.size(), &e)) {
88       return std::nullopt;
89     }
90     return detail::cvt_extern(e);
91   }
92 
93   /**
94    * \brief Load an instance's export by index.
95    *
96    * This function will look for the `idx`th export of this instance. This will
97    * return both the name of the export as well as the exported item itself.
98    */
99   std::optional<std::pair<std::string_view, Extern>> get(Store::Context cx,
100                                                          size_t idx) {
101     wasmtime_extern_t e;
102     // I'm not sure why clang-tidy thinks this is using va_list or anything
103     // related to that...
104     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
105     char *name = nullptr;
106     size_t len = 0;
107     if (!wasmtime_instance_export_nth(cx.ptr, &instance, idx, &name, &len,
108                                       &e)) {
109       return std::nullopt;
110     }
111     std::string_view n(name, len);
112     return std::pair(n, detail::cvt_extern(e));
113   }
114 };
115 
116 } // namespace wasmtime
117 
118 #endif // WASMTIME_INSTANCE_HH
119