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