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