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}