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