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