| 254 | } |
| 255 | |
| 256 | pub(crate) unsafe fn c_callback_to_rust_fn( |
| 257 | callback: wasmtime_func_callback_t, |
| 258 | data: *mut c_void, |
| 259 | finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>, |
| 260 | ) -> impl Fn(WasmtimeCaller<'_>, &[Val], &mut [Val]) -> Result<()> { |
| 261 | let foreign = crate::ForeignData { data, finalizer }; |
| 262 | move |mut caller, params, results| { |
| 263 | let _ = &foreign; // move entire foreign into this closure |
| 264 | |
| 265 | // Convert `params/results` to `wasmtime_val_t`. Use the previous |
| 266 | // storage in `hostcall_val_storage` to help avoid allocations all the |
| 267 | // time. |
| 268 | let mut vals = mem::take(&mut caller.data_mut().hostcall_val_storage); |
| 269 | debug_assert!(vals.is_empty()); |
| 270 | vals.reserve(params.len() + results.len()); |
| 271 | vals.extend( |
| 272 | params |
| 273 | .iter() |
| 274 | .cloned() |
| 275 | .map(|p| wasmtime_val_t::from_val_unscoped(&mut caller, p)), |
| 276 | ); |
| 277 | vals.extend((0..results.len()).map(|_| wasmtime_val_t { |
| 278 | kind: crate::WASMTIME_I32, |
| 279 | of: wasmtime_val_union { i32: 0 }, |
| 280 | })); |
| 281 | let (params, out_results) = vals.split_at_mut(params.len()); |
| 282 | |
| 283 | // Invoke the C function pointer, getting the results. |
| 284 | let mut caller = wasmtime_caller_t { caller }; |
| 285 | let out = callback( |
| 286 | foreign.data, |
| 287 | &mut caller, |
| 288 | params.as_ptr(), |
| 289 | params.len(), |
| 290 | out_results.as_mut_ptr(), |
| 291 | out_results.len(), |
| 292 | ); |
| 293 | if let Some(trap) = out { |
| 294 | return Err(trap.error); |
| 295 | } |
| 296 | |
| 297 | // Translate the `wasmtime_val_t` results into the `results` space |
| 298 | for (i, result) in out_results.iter().enumerate() { |
| 299 | results[i] = result.to_val_unscoped(&mut caller); |
| 300 | } |
| 301 | |
| 302 | // Move our `vals` storage back into the store now that we no longer |
| 303 | // need it. This'll get picked up by the next hostcall and reuse our |
| 304 | // same storage. |
| 305 | vals.truncate(0); |
| 306 | caller.caller.data_mut().hostcall_val_storage = vals; |
| 307 | Ok(()) |
| 308 | } |
| 309 | } |
| 310 | |
| 311 | #[unsafe(no_mangle)] |
| 312 | pub unsafe extern "C" fn wasmtime_func_new_unchecked( |