wasmer_c_api/wasm_c_api/engine/
mod.rs

1pub use super::unstable::engine::wasm_config_set_features;
2use super::unstable::features::wasmer_features_t;
3
4use wasmer_api::{BackendKind, Engine};
5
6mod config;
7#[allow(unused_imports)]
8pub use config::*;
9
10/// Kind of engines that can be used by the store.
11///
12/// This is a Wasmer-specific type with Wasmer-specific functions for
13/// manipulating it.
14#[derive(Debug, Copy, Clone)]
15#[repr(C)]
16#[allow(non_camel_case_types)]
17pub enum wasmer_backend_t {
18    /// The cranelift backend.
19    CRANELIFT = 0,
20
21    /// The LLVM backend.
22    LLVM,
23
24    /// The singlepass backend.
25    SINGLEPASS,
26
27    /// The headless backend.
28    HEADLESS,
29
30    /// The V8 backend.
31    V8,
32
33    /// The JSC backend.
34    JSC,
35}
36
37impl From<BackendKind> for wasmer_backend_t {
38    fn from(value: BackendKind) -> Self {
39        match value {
40            #[cfg(feature = "cranelift")]
41            BackendKind::Cranelift => Self::CRANELIFT,
42            #[cfg(feature = "llvm")]
43            BackendKind::LLVM => Self::LLVM,
44            #[cfg(feature = "singlepass")]
45            BackendKind::Singlepass => Self::SINGLEPASS,
46            #[cfg(feature = "sys")]
47            BackendKind::Headless => Self::HEADLESS,
48            #[cfg(feature = "v8")]
49            BackendKind::V8 => Self::V8,
50            #[cfg(feature = "jsc")]
51            BackendKind::Jsc => Self::JSC,
52            v => panic!("Unsupported backend kind {v:?}"),
53        }
54    }
55}
56
57impl Default for wasmer_backend_t {
58    fn default() -> Self {
59        // Let the `wasmer_api` crate decide which is the default engine, given the enabled
60        // features.
61        wasmer_api::BackendKind::default().into()
62    }
63}
64
65/// An engine is used by the store to drive the compilation and the
66/// execution of a WebAssembly module.
67///
68/// cbindgen:ignore
69#[repr(C)]
70// We can let the API decide which engine is default with the given set of
71// features.
72//
73// See the impl of `Default` for `BackendEngine` in the `wasmer` (API) crate.
74#[derive(Default)]
75pub struct wasm_engine_t {
76    pub(crate) inner: Engine,
77}
78
79#[unsafe(no_mangle)]
80#[allow(unreachable_code)]
81pub extern "C" fn wasm_engine_new() -> Box<wasm_engine_t> {
82    Box::new(wasm_engine_t::default())
83}
84
85/// Deletes an engine.
86///
87/// # Example
88///
89/// ```rust
90/// # use wasmer_inline_c::assert_c;
91/// # fn main() {
92/// #    (assert_c! {
93/// # #include "tests/wasmer.h"
94/// #
95/// int main() {
96///     // Create a default engine.
97///     wasm_engine_t* engine = wasm_engine_new();
98///     int error_length = wasmer_last_error_length();
99///     if (error_length > 0) {
100///         char *error_message = malloc(error_length);
101///         wasmer_last_error_message(error_message, error_length);
102///
103///         printf("Attempted to set an immutable global: `%s`\n", error_message);
104///         free(error_message);
105///     }
106///
107///     // Check we have an engine!
108///     assert(engine);
109///
110///     // Free everything.
111///     wasm_engine_delete(engine);
112///
113///     return 0;
114/// }
115/// #    })
116/// #    .success();
117/// # }
118/// ```
119///
120/// cbindgen:ignore
121#[unsafe(no_mangle)]
122pub unsafe extern "C" fn wasm_engine_delete(_engine: Option<Box<wasm_engine_t>>) {}
123
124/// Creates an engine with a particular configuration.
125///
126/// # Example
127///
128/// See [`wasm_config_new`].
129///
130/// cbindgen:ignore
131#[unsafe(no_mangle)]
132pub extern "C" fn wasm_engine_new_with_config(
133    config: Option<Box<wasm_config_t>>,
134) -> Option<Box<wasm_engine_t>> {
135    #[allow(unused)]
136    let config = *(config?);
137
138    match config.backend {
139        #[cfg(feature = "llvm")]
140        wasmer_backend_t::LLVM => config::sys::wasm_sys_engine_new_with_config(config),
141        #[cfg(feature = "cranelift")]
142        wasmer_backend_t::CRANELIFT => config::sys::wasm_sys_engine_new_with_config(config),
143        #[cfg(feature = "singlepass")]
144        wasmer_backend_t::SINGLEPASS => config::sys::wasm_sys_engine_new_with_config(config),
145        #[cfg(feature = "sys")]
146        wasmer_backend_t::HEADLESS => config::sys::wasm_sys_engine_new_with_config(config),
147        #[cfg(feature = "v8")]
148        wasmer_backend_t::V8 => config::v8::wasm_v8_engine_new_with_config(config),
149        #[cfg(feature = "jsc")]
150        wasmer_backend_t::JSC => config::jsc::wasm_jsc_engine_new_with_config(config),
151        #[allow(unreachable_patterns)]
152        _ => unreachable!(),
153    }
154}
155
156/// A configuration holds the compiler and the engine used by the store.
157///
158/// cbindgen:ignore
159#[derive(Debug, Default)]
160#[repr(C)]
161pub struct wasm_config_t {
162    pub(super) backend: wasmer_backend_t,
163    pub(super) backend_config: wasmer_backend_config_t,
164    pub(super) features: Option<Box<wasmer_features_t>>,
165}
166
167/// Create a new default Wasmer configuration.
168///
169/// # Example
170///
171/// ```rust
172/// # use wasmer_inline_c::assert_c;
173/// # fn main() {
174/// #    (assert_c! {
175/// # #include "tests/wasmer.h"
176/// #
177/// int main() {
178///     // Create the configuration.
179///     wasm_config_t* config = wasm_config_new();
180///
181///     // Create the engine.
182///     wasm_engine_t* engine = wasm_engine_new_with_config(config);
183///
184///     // Check we have an engine!
185///     assert(engine);
186///
187///     // Free everything.
188///     wasm_engine_delete(engine);
189///
190///     return 0;
191/// }
192/// #    })
193/// #    .success();
194/// # }
195/// ```
196///
197/// cbindgen:ignore
198#[unsafe(no_mangle)]
199pub extern "C" fn wasm_config_new() -> Box<wasm_config_t> {
200    Box::<wasm_config_t>::default()
201}
202
203/// Delete a Wasmer config object.
204///
205/// This function does not need to be called if `wasm_engine_new_with_config` or
206/// another function that takes ownership of the `wasm_config_t` is called.
207///
208/// # Example
209///
210/// ```rust
211/// # use wasmer_inline_c::assert_c;
212/// # fn main() {
213/// #    (assert_c! {
214/// # #include "tests/wasmer.h"
215/// #
216/// int main() {
217///     // Create the configuration.
218///     wasm_config_t* config = wasm_config_new();
219///
220///     // Delete the configuration
221///     wasm_config_delete(config);
222///
223///     return 0;
224/// }
225/// #    })
226/// #    .success();
227/// # }
228/// ```
229/// cbindgen:ignore
230#[unsafe(no_mangle)]
231pub extern "C" fn wasm_config_delete(_config: Option<Box<wasm_config_t>>) {}
232
233/// Updates the configuration to specify a particular engine to use.
234///
235/// This is a Wasmer-specific function.
236///
237/// # Example
238///
239/// ```rust
240/// # use wasmer_inline_c::assert_c;
241/// # fn main() {
242/// #    (assert_c! {
243/// # #include "tests/wasmer.h"
244/// #
245/// int main() {
246///     // Create the configuration.
247///     wasm_config_t* config = wasm_config_new();
248///
249///     // Create the engine.
250///     wasm_engine_t* engine = wasm_engine_new_with_config(config);
251///
252///     // Check we have an engine!
253///     assert(engine);
254///
255///     // Free everything.
256///     wasm_engine_delete(engine);
257///
258///     return 0;
259/// }
260/// #    })
261/// #    .success();
262/// # }
263/// ```
264#[unsafe(no_mangle)]
265pub extern "C" fn wasm_config_set_backend(config: &mut wasm_config_t, engine: wasmer_backend_t) {
266    config.backend = engine;
267}
268
269#[cfg(test)]
270mod tests {
271    #[cfg(not(target_os = "windows"))]
272    use inline_c::assert_c;
273    #[cfg(target_os = "windows")]
274    use wasmer_inline_c::assert_c;
275
276    #[allow(
277        unexpected_cfgs,
278        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
279    )]
280    #[cfg_attr(coverage_nightly, coverage(off))]
281    #[test]
282    fn test_engine_new() {
283        (assert_c! {
284            #include "tests/wasmer.h"
285
286            int main() {
287                wasm_engine_t* engine = wasm_engine_new();
288                assert(engine);
289
290                wasm_engine_delete(engine);
291
292                return 0;
293            }
294        })
295        .success();
296    }
297}