wasmer_c_api/wasm_c_api/externals/
global.rs

1use super::super::store::wasm_store_t;
2use super::super::types::wasm_globaltype_t;
3use super::super::value::wasm_val_t;
4use super::wasm_extern_t;
5use std::convert::TryInto;
6use wasmer_api::{Extern, Global, Value};
7
8#[allow(non_camel_case_types)]
9#[repr(C)]
10#[derive(Clone)]
11pub struct wasm_global_t {
12    pub(crate) extern_: wasm_extern_t,
13}
14
15impl wasm_global_t {
16    pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_global_t> {
17        match &e.inner {
18            Extern::Global(_) => Some(unsafe { &*(e as *const _ as *const _) }),
19            _ => None,
20        }
21    }
22}
23
24#[unsafe(no_mangle)]
25pub unsafe extern "C" fn wasm_global_new(
26    store: Option<&mut wasm_store_t>,
27    global_type: Option<&wasm_globaltype_t>,
28    val: Option<&wasm_val_t>,
29) -> Option<Box<wasm_global_t>> {
30    let global_type = global_type?;
31    let store = store?;
32    let mut store_mut = unsafe { store.inner.store_mut() };
33    let val = val?;
34
35    let global_type = &global_type.inner().global_type;
36    let wasm_val = val.try_into().ok()?;
37    let global = if global_type.mutability.is_mutable() {
38        Global::new_mut(&mut store_mut, wasm_val)
39    } else {
40        Global::new(&mut store_mut, wasm_val)
41    };
42    Some(Box::new(wasm_global_t {
43        extern_: wasm_extern_t::new(store.inner.clone(), global.into()),
44    }))
45}
46
47#[unsafe(no_mangle)]
48pub unsafe extern "C" fn wasm_global_delete(_global: Option<Box<wasm_global_t>>) {}
49
50#[unsafe(no_mangle)]
51pub unsafe extern "C" fn wasm_global_copy(global: &wasm_global_t) -> Box<wasm_global_t> {
52    // do shallow copy
53    Box::new(global.clone())
54}
55
56#[unsafe(no_mangle)]
57pub unsafe extern "C" fn wasm_global_get(
58    global: &mut wasm_global_t,
59    // own
60    out: &mut wasm_val_t,
61) {
62    let wasm_global = global.extern_.global();
63    let mut store_mut = unsafe { global.extern_.store.store_mut() };
64    let value = wasm_global.get(&mut store_mut);
65    *out = value.try_into().unwrap();
66}
67
68/// Note: This function returns nothing by design but it can raise an
69/// error if setting a new value fails.
70#[unsafe(no_mangle)]
71pub unsafe extern "C" fn wasm_global_set(global: &mut wasm_global_t, val: &wasm_val_t) {
72    let value: Value = val.try_into().unwrap();
73    let wasm_global = global.extern_.global();
74    let mut store_mut = unsafe { global.extern_.store.store_mut() };
75    c_try!(wasm_global.set(&mut store_mut, value); otherwise ());
76}
77
78#[unsafe(no_mangle)]
79pub unsafe extern "C" fn wasm_global_same(
80    wasm_global1: &wasm_global_t,
81    wasm_global2: &wasm_global_t,
82) -> bool {
83    wasm_global1.extern_.global() == wasm_global2.extern_.global()
84}
85
86#[unsafe(no_mangle)]
87pub unsafe extern "C" fn wasm_global_type(
88    global: Option<&wasm_global_t>,
89) -> Option<Box<wasm_globaltype_t>> {
90    let global = global?;
91    let store_ref = unsafe { global.extern_.store.store() };
92    Some(Box::new(wasm_globaltype_t::new(
93        global.extern_.global().ty(&store_ref),
94    )))
95}
96
97#[cfg(test)]
98mod tests {
99    #[cfg(not(target_os = "windows"))]
100    use inline_c::assert_c;
101    #[cfg(target_os = "windows")]
102    use wasmer_inline_c::assert_c;
103
104    #[allow(
105        unexpected_cfgs,
106        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
107    )]
108    #[cfg_attr(coverage_nightly, coverage(off))]
109    #[test]
110    fn test_set_host_global_immutable() {
111        (assert_c! {
112            #include "tests/wasmer.h"
113
114            int main() {
115                wasm_engine_t* engine = wasm_engine_new();
116                wasm_store_t* store = wasm_store_new(engine);
117
118                wasm_val_t forty_two = WASM_F32_VAL(42);
119                wasm_val_t forty_three = WASM_F32_VAL(43);
120
121                wasm_valtype_t* valtype = wasm_valtype_new_i32();
122                wasm_globaltype_t* global_type = wasm_globaltype_new(valtype, WASM_CONST);
123                wasm_global_t* global = wasm_global_new(store, global_type, &forty_two);
124
125                wasm_globaltype_delete(global_type);
126
127                wasm_global_set(global, &forty_three);
128
129                assert(wasmer_last_error_length() > 0);
130
131                wasm_global_delete(global);
132                wasm_store_delete(store);
133                wasm_engine_delete(engine);
134
135                return 0;
136            }
137        })
138        .success();
139    }
140
141    #[allow(
142        unexpected_cfgs,
143        reason = "tools like cargo-llvm-coverage pass --cfg coverage"
144    )]
145    #[cfg_attr(coverage_nightly, coverage(off))]
146    #[test]
147    fn test_set_guest_global_immutable() {
148        (assert_c! {
149            #include "tests/wasmer.h"
150
151            int main() {
152                wasm_engine_t* engine = wasm_engine_new();
153                wasm_store_t* store = wasm_store_new(engine);
154
155                wasm_byte_vec_t wat;
156                wasmer_byte_vec_new_from_string(&wat, "(module (global $global (export \"global\") f32 (f32.const 1)))");
157                wasm_byte_vec_t wasm_bytes;
158                wat2wasm(&wat, &wasm_bytes);
159                wasm_module_t* module = wasm_module_new(store, &wasm_bytes);
160                wasm_extern_vec_t import_object = WASM_EMPTY_VEC;
161                wasm_instance_t* instance = wasm_instance_new(store, module, &import_object, NULL);
162
163                wasm_extern_vec_t exports;
164                wasm_instance_exports(instance, &exports);
165                wasm_global_t* global = wasm_extern_as_global(exports.data[0]);
166
167                wasm_val_t forty_two = WASM_F32_VAL(42);
168                wasm_global_set(global, &forty_two);
169
170                printf("%d", wasmer_last_error_length());
171                assert(wasmer_last_error_length() > 0);
172
173                wasm_instance_delete(instance);
174                wasm_byte_vec_delete(&wasm_bytes);
175                wasm_byte_vec_delete(&wat);
176                wasm_extern_vec_delete(&exports);
177                wasm_store_delete(store);
178                wasm_engine_delete(engine);
179
180                return 0;
181            }
182        })
183        .success();
184    }
185}