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