wasmer_c_api/wasm_c_api/externals/
global.rs1use 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 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 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#[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}