1 use crate::{ 2 bad_utf8, handle_result, wasm_engine_t, wasm_functype_t, wasm_trap_t, wasmtime_error_t, 3 wasmtime_extern_t, wasmtime_instance_pre_t, wasmtime_module_t, WasmtimeStoreContext, 4 WasmtimeStoreContextMut, 5 }; 6 use std::ffi::c_void; 7 use std::mem::MaybeUninit; 8 use std::str; 9 use wasmtime::{Func, Instance, Linker}; 10 11 #[repr(C)] 12 pub struct wasmtime_linker_t { 13 pub(crate) linker: Linker<crate::WasmtimeStoreData>, 14 } 15 16 wasmtime_c_api_macros::declare_own!(wasmtime_linker_t); 17 18 #[no_mangle] 19 pub extern "C" fn wasmtime_linker_new(engine: &wasm_engine_t) -> Box<wasmtime_linker_t> { 20 Box::new(wasmtime_linker_t { 21 linker: Linker::new(&engine.engine), 22 }) 23 } 24 25 #[no_mangle] 26 pub extern "C" fn wasmtime_linker_clone(linker: &wasmtime_linker_t) -> Box<wasmtime_linker_t> { 27 Box::new(wasmtime_linker_t { 28 linker: linker.linker.clone(), 29 }) 30 } 31 32 #[no_mangle] 33 pub extern "C" fn wasmtime_linker_allow_shadowing( 34 linker: &mut wasmtime_linker_t, 35 allow_shadowing: bool, 36 ) { 37 linker.linker.allow_shadowing(allow_shadowing); 38 } 39 40 macro_rules! to_str { 41 ($ptr:expr, $len:expr) => { 42 match str::from_utf8(crate::slice_from_raw_parts($ptr, $len)) { 43 Ok(s) => s, 44 Err(_) => return bad_utf8(), 45 } 46 }; 47 } 48 49 pub(crate) use to_str; 50 51 #[no_mangle] 52 pub unsafe extern "C" fn wasmtime_linker_define( 53 linker: &mut wasmtime_linker_t, 54 store: WasmtimeStoreContext<'_>, 55 module: *const u8, 56 module_len: usize, 57 name: *const u8, 58 name_len: usize, 59 item: &wasmtime_extern_t, 60 ) -> Option<Box<wasmtime_error_t>> { 61 let linker = &mut linker.linker; 62 let module = to_str!(module, module_len); 63 let name = to_str!(name, name_len); 64 let item = item.to_extern(); 65 handle_result(linker.define(&store, module, name, item), |_linker| ()) 66 } 67 68 #[no_mangle] 69 pub unsafe extern "C" fn wasmtime_linker_define_func( 70 linker: &mut wasmtime_linker_t, 71 module: *const u8, 72 module_len: usize, 73 name: *const u8, 74 name_len: usize, 75 ty: &wasm_functype_t, 76 callback: crate::wasmtime_func_callback_t, 77 data: *mut c_void, 78 finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>, 79 ) -> Option<Box<wasmtime_error_t>> { 80 let ty = ty.ty().ty(linker.linker.engine()); 81 let module = to_str!(module, module_len); 82 let name = to_str!(name, name_len); 83 let cb = crate::func::c_callback_to_rust_fn(callback, data, finalizer); 84 handle_result(linker.linker.func_new(module, name, ty, cb), |_linker| ()) 85 } 86 87 #[no_mangle] 88 pub unsafe extern "C" fn wasmtime_linker_define_func_unchecked( 89 linker: &mut wasmtime_linker_t, 90 module: *const u8, 91 module_len: usize, 92 name: *const u8, 93 name_len: usize, 94 ty: &wasm_functype_t, 95 callback: crate::wasmtime_func_unchecked_callback_t, 96 data: *mut c_void, 97 finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>, 98 ) -> Option<Box<wasmtime_error_t>> { 99 let ty = ty.ty().ty(linker.linker.engine()); 100 let module = to_str!(module, module_len); 101 let name = to_str!(name, name_len); 102 let cb = crate::func::c_unchecked_callback_to_rust_fn(callback, data, finalizer); 103 handle_result( 104 linker.linker.func_new_unchecked(module, name, ty, cb), 105 |_linker| (), 106 ) 107 } 108 109 #[cfg(feature = "wasi")] 110 #[no_mangle] 111 pub extern "C" fn wasmtime_linker_define_wasi( 112 linker: &mut wasmtime_linker_t, 113 ) -> Option<Box<wasmtime_error_t>> { 114 handle_result( 115 wasmtime_wasi::preview1::add_to_linker_sync(&mut linker.linker, |ctx| { 116 ctx.wasi.as_mut().expect("wasi context must be populated") 117 }), 118 |_linker| (), 119 ) 120 } 121 122 #[no_mangle] 123 pub unsafe extern "C" fn wasmtime_linker_define_instance( 124 linker: &mut wasmtime_linker_t, 125 store: WasmtimeStoreContextMut<'_>, 126 name: *const u8, 127 name_len: usize, 128 instance: &Instance, 129 ) -> Option<Box<wasmtime_error_t>> { 130 let linker = &mut linker.linker; 131 let name = to_str!(name, name_len); 132 handle_result(linker.instance(store, name, *instance), |_linker| ()) 133 } 134 135 #[no_mangle] 136 pub extern "C" fn wasmtime_linker_instantiate( 137 linker: &wasmtime_linker_t, 138 store: WasmtimeStoreContextMut<'_>, 139 module: &wasmtime_module_t, 140 instance_ptr: &mut Instance, 141 trap_ptr: &mut *mut wasm_trap_t, 142 ) -> Option<Box<wasmtime_error_t>> { 143 let result = linker.linker.instantiate(store, &module.module); 144 super::instance::handle_instantiate(result, instance_ptr, trap_ptr) 145 } 146 147 #[no_mangle] 148 pub unsafe extern "C" fn wasmtime_linker_instantiate_pre( 149 linker: &wasmtime_linker_t, 150 module: &wasmtime_module_t, 151 instance_ptr: &mut *mut wasmtime_instance_pre_t, 152 ) -> Option<Box<wasmtime_error_t>> { 153 let linker = &linker.linker; 154 handle_result(linker.instantiate_pre(&module.module), |i| { 155 let instance_pre = Box::new(wasmtime_instance_pre_t { underlying: i }); 156 *instance_ptr = Box::into_raw(instance_pre) 157 }) 158 } 159 160 #[no_mangle] 161 pub unsafe extern "C" fn wasmtime_linker_module( 162 linker: &mut wasmtime_linker_t, 163 store: WasmtimeStoreContextMut<'_>, 164 name: *const u8, 165 name_len: usize, 166 module: &wasmtime_module_t, 167 ) -> Option<Box<wasmtime_error_t>> { 168 let linker = &mut linker.linker; 169 let name = to_str!(name, name_len); 170 handle_result(linker.module(store, name, &module.module), |_linker| ()) 171 } 172 173 #[no_mangle] 174 pub unsafe extern "C" fn wasmtime_linker_get_default( 175 linker: &wasmtime_linker_t, 176 store: WasmtimeStoreContextMut<'_>, 177 name: *const u8, 178 name_len: usize, 179 func: &mut Func, 180 ) -> Option<Box<wasmtime_error_t>> { 181 let linker = &linker.linker; 182 let name = to_str!(name, name_len); 183 handle_result(linker.get_default(store, name), |f| *func = f) 184 } 185 186 #[no_mangle] 187 pub unsafe extern "C" fn wasmtime_linker_get( 188 linker: &wasmtime_linker_t, 189 store: WasmtimeStoreContextMut<'_>, 190 module: *const u8, 191 module_len: usize, 192 name: *const u8, 193 name_len: usize, 194 item_ptr: &mut MaybeUninit<wasmtime_extern_t>, 195 ) -> bool { 196 let linker = &linker.linker; 197 let module = match str::from_utf8(crate::slice_from_raw_parts(module, module_len)) { 198 Ok(s) => s, 199 Err(_) => return false, 200 }; 201 let name = match str::from_utf8(crate::slice_from_raw_parts(name, name_len)) { 202 Ok(s) => s, 203 Err(_) => return false, 204 }; 205 match linker.get(store, module, name) { 206 Some(which) => { 207 crate::initialize(item_ptr, which.into()); 208 true 209 } 210 None => false, 211 } 212 } 213