1 use crate::{ 2 wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_store_t, wasm_trap_t, wasmtime_error_t, 3 wasmtime_extern_t, wasmtime_module_t, WasmStoreRef, WasmtimeStoreContextMut, WasmtimeStoreData, 4 }; 5 use std::mem::MaybeUninit; 6 use wasmtime::{Instance, InstancePre, Trap}; 7 8 #[derive(Clone)] 9 pub struct wasm_instance_t { 10 store: WasmStoreRef, 11 instance: Instance, 12 } 13 14 wasmtime_c_api_macros::declare_ref!(wasm_instance_t); 15 16 impl wasm_instance_t { 17 pub(crate) fn new(store: WasmStoreRef, instance: Instance) -> wasm_instance_t { 18 wasm_instance_t { store, instance } 19 } 20 } 21 22 #[unsafe(no_mangle)] 23 pub unsafe extern "C" fn wasm_instance_new( 24 store: &mut wasm_store_t, 25 wasm_module: &wasm_module_t, 26 imports: *const wasm_extern_vec_t, 27 result: Option<&mut *mut wasm_trap_t>, 28 ) -> Option<Box<wasm_instance_t>> { 29 let imports = (*imports) 30 .as_slice() 31 .iter() 32 .filter_map(|import| match import { 33 Some(i) => Some(i.which.clone()), 34 None => None, 35 }) 36 .collect::<Vec<_>>(); 37 match Instance::new(store.store.context_mut(), &wasm_module.module, &imports) { 38 Ok(instance) => Some(Box::new(wasm_instance_t::new( 39 store.store.clone(), 40 instance, 41 ))), 42 Err(e) => { 43 if let Some(ptr) = result { 44 *ptr = Box::into_raw(Box::new(wasm_trap_t::new(e))); 45 } 46 None 47 } 48 } 49 } 50 51 #[unsafe(no_mangle)] 52 pub unsafe extern "C" fn wasm_instance_exports( 53 instance: &mut wasm_instance_t, 54 out: &mut wasm_extern_vec_t, 55 ) { 56 let store = instance.store.clone(); 57 out.set_buffer( 58 instance 59 .instance 60 .exports(instance.store.context_mut()) 61 .map(|e| { 62 Some(Box::new(wasm_extern_t { 63 which: e.into_extern(), 64 store: store.clone(), 65 })) 66 }) 67 .collect(), 68 ); 69 } 70 71 #[unsafe(no_mangle)] 72 pub unsafe extern "C" fn wasmtime_instance_new( 73 store: WasmtimeStoreContextMut<'_>, 74 module: &wasmtime_module_t, 75 imports: *const wasmtime_extern_t, 76 nimports: usize, 77 instance: &mut Instance, 78 trap_ptr: &mut *mut wasm_trap_t, 79 ) -> Option<Box<wasmtime_error_t>> { 80 let imports = crate::slice_from_raw_parts(imports, nimports) 81 .iter() 82 .map(|i| i.to_extern()) 83 .collect::<Vec<_>>(); 84 handle_instantiate( 85 Instance::new(store, &module.module, &imports), 86 instance, 87 trap_ptr, 88 ) 89 } 90 91 pub(crate) fn handle_instantiate( 92 instance: anyhow::Result<Instance>, 93 instance_ptr: &mut Instance, 94 trap_ptr: &mut *mut wasm_trap_t, 95 ) -> Option<Box<wasmtime_error_t>> { 96 match instance { 97 Ok(i) => { 98 *instance_ptr = i; 99 None 100 } 101 Err(e) => { 102 if e.is::<Trap>() { 103 *trap_ptr = Box::into_raw(Box::new(wasm_trap_t::new(e))); 104 None 105 } else { 106 Some(Box::new(e.into())) 107 } 108 } 109 } 110 } 111 112 #[unsafe(no_mangle)] 113 pub unsafe extern "C" fn wasmtime_instance_export_get( 114 store: WasmtimeStoreContextMut<'_>, 115 instance: &Instance, 116 name: *const u8, 117 name_len: usize, 118 item: &mut MaybeUninit<wasmtime_extern_t>, 119 ) -> bool { 120 let name = crate::slice_from_raw_parts(name, name_len); 121 let name = match std::str::from_utf8(name) { 122 Ok(name) => name, 123 Err(_) => return false, 124 }; 125 match instance.get_export(store, name) { 126 Some(e) => { 127 crate::initialize(item, e.into()); 128 true 129 } 130 None => false, 131 } 132 } 133 134 #[unsafe(no_mangle)] 135 pub unsafe extern "C" fn wasmtime_instance_export_nth( 136 store: WasmtimeStoreContextMut<'_>, 137 instance: &Instance, 138 index: usize, 139 name_ptr: &mut *const u8, 140 name_len: &mut usize, 141 item: &mut MaybeUninit<wasmtime_extern_t>, 142 ) -> bool { 143 match instance.exports(store).nth(index) { 144 Some(e) => { 145 *name_ptr = e.name().as_ptr(); 146 *name_len = e.name().len(); 147 crate::initialize(item, e.into_extern().into()); 148 true 149 } 150 None => false, 151 } 152 } 153 154 #[repr(transparent)] 155 pub struct wasmtime_instance_pre_t { 156 pub(crate) underlying: InstancePre<WasmtimeStoreData>, 157 } 158 159 #[unsafe(no_mangle)] 160 pub unsafe extern "C" fn wasmtime_instance_pre_delete(_instance_pre: Box<wasmtime_instance_pre_t>) { 161 } 162 163 #[unsafe(no_mangle)] 164 pub unsafe extern "C" fn wasmtime_instance_pre_instantiate( 165 instance_pre: &wasmtime_instance_pre_t, 166 store: WasmtimeStoreContextMut<'_>, 167 instance_ptr: &mut Instance, 168 trap_ptr: &mut *mut wasm_trap_t, 169 ) -> Option<Box<wasmtime_error_t>> { 170 let result = instance_pre.underlying.instantiate(store); 171 handle_instantiate(result, instance_ptr, trap_ptr) 172 } 173 174 #[unsafe(no_mangle)] 175 pub unsafe extern "C" fn wasmtime_instance_pre_module( 176 instance_pre: &wasmtime_instance_pre_t, 177 ) -> Box<wasmtime_module_t> { 178 let module = instance_pre.underlying.module().clone(); 179 Box::new(wasmtime_module_t { module }) 180 } 181