1 use crate::{wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_trap_t}; 2 use crate::{wasm_store_t, wasmtime_error_t}; 3 use anyhow::Result; 4 use std::ptr; 5 use wasmtime::{Instance, Trap}; 6 7 #[repr(C)] 8 #[derive(Clone)] 9 pub struct wasm_instance_t { 10 pub(crate) instance: Instance, 11 } 12 13 wasmtime_c_api_macros::declare_ref!(wasm_instance_t); 14 15 impl wasm_instance_t { 16 pub(crate) fn new(instance: Instance) -> wasm_instance_t { 17 wasm_instance_t { instance: instance } 18 } 19 } 20 21 #[no_mangle] 22 pub unsafe extern "C" fn wasm_instance_new( 23 store: &wasm_store_t, 24 wasm_module: &wasm_module_t, 25 imports: *const Box<wasm_extern_t>, 26 result: Option<&mut *mut wasm_trap_t>, 27 ) -> Option<Box<wasm_instance_t>> { 28 let mut instance = ptr::null_mut(); 29 let mut trap = ptr::null_mut(); 30 let err = wasmtime_instance_new( 31 store, 32 wasm_module, 33 imports, 34 wasm_module.imports.len(), 35 &mut instance, 36 &mut trap, 37 ); 38 match err { 39 Some(err) => { 40 assert!(trap.is_null()); 41 assert!(instance.is_null()); 42 if let Some(result) = result { 43 *result = Box::into_raw(err.to_trap()); 44 } 45 None 46 } 47 None => { 48 if instance.is_null() { 49 assert!(!trap.is_null()); 50 if let Some(result) = result { 51 *result = trap; 52 } else { 53 drop(Box::from_raw(trap)) 54 } 55 None 56 } else { 57 assert!(trap.is_null()); 58 Some(Box::from_raw(instance)) 59 } 60 } 61 } 62 } 63 64 #[no_mangle] 65 pub unsafe extern "C" fn wasmtime_instance_new( 66 store: &wasm_store_t, 67 module: &wasm_module_t, 68 imports: *const Box<wasm_extern_t>, 69 num_imports: usize, 70 instance_ptr: &mut *mut wasm_instance_t, 71 trap_ptr: &mut *mut wasm_trap_t, 72 ) -> Option<Box<wasmtime_error_t>> { 73 _wasmtime_instance_new( 74 store, 75 module, 76 std::slice::from_raw_parts(imports, num_imports), 77 instance_ptr, 78 trap_ptr, 79 ) 80 } 81 82 fn _wasmtime_instance_new( 83 store: &wasm_store_t, 84 module: &wasm_module_t, 85 imports: &[Box<wasm_extern_t>], 86 instance_ptr: &mut *mut wasm_instance_t, 87 trap_ptr: &mut *mut wasm_trap_t, 88 ) -> Option<Box<wasmtime_error_t>> { 89 let store = &store.store; 90 let imports = imports 91 .iter() 92 .map(|import| import.which.clone()) 93 .collect::<Vec<_>>(); 94 handle_instantiate( 95 Instance::new(store, &module.module, &imports), 96 instance_ptr, 97 trap_ptr, 98 ) 99 } 100 101 pub fn handle_instantiate( 102 instance: Result<Instance>, 103 instance_ptr: &mut *mut wasm_instance_t, 104 trap_ptr: &mut *mut wasm_trap_t, 105 ) -> Option<Box<wasmtime_error_t>> { 106 fn write<T>(ptr: &mut *mut T, val: T) { 107 *ptr = Box::into_raw(Box::new(val)) 108 } 109 110 match instance { 111 Ok(instance) => { 112 write(instance_ptr, wasm_instance_t::new(instance)); 113 None 114 } 115 Err(e) => match e.downcast::<Trap>() { 116 Ok(trap) => { 117 write(trap_ptr, wasm_trap_t::new(trap)); 118 None 119 } 120 Err(e) => Some(Box::new(e.into())), 121 }, 122 } 123 } 124 125 #[no_mangle] 126 pub extern "C" fn wasm_instance_exports(instance: &wasm_instance_t, out: &mut wasm_extern_vec_t) { 127 out.set_buffer( 128 instance 129 .instance 130 .exports() 131 .map(|e| { 132 Some(Box::new(wasm_extern_t { 133 which: e.into_extern(), 134 })) 135 }) 136 .collect(), 137 ); 138 } 139