Builds a NativeBinding that marshals handles around `host_call_native`. Kept out of resolver.rs so the resolver stays ABI-agnostic. */
(name: String, id: u32)
| 340 | |
| 341 | /* Builds a NativeBinding that marshals handles around `host_call_native`. Kept out of resolver.rs so the resolver stays ABI-agnostic. */ |
| 342 | pub(super) fn make_native_binding(name: String, id: u32) -> NativeBinding { |
| 343 | let closure = move |_: &mut crate::modules::vm::types::HeapPool, args: &[Val], kwargs: Option<Val>| -> Result<Val, VmErr> { |
| 344 | /* 1. Register positional args as handles the guest will see; append the kwargs handle (0 means no kwargs). */ |
| 345 | let mut argv: Vec<u32> = args.iter().map(|v| put_val(*v)).collect(); |
| 346 | argv.push(kwargs.map_or(0, put_val)); |
| 347 | let mut out_handle: u32 = 0; |
| 348 | |
| 349 | // call_id is what call_extern will park with on defer; lets the host route the result back. |
| 350 | let call_id = with_vm(|vm| vm.next_host_call_id as u32).unwrap_or(0); |
| 351 | let status = unsafe { |
| 352 | host_call_native( |
| 353 | id, call_id, |
| 354 | argv.as_ptr(), argv.len() as u32, |
| 355 | &mut out_handle as *mut u32, |
| 356 | ) |
| 357 | }; |
| 358 | |
| 359 | /* 3. Read result BEFORE releasing argv: a returned input would point into slots we're about to free. */ |
| 360 | // Status 2 = DEFERRED: handler has captured what it needs; release argv and park the VM. |
| 361 | if status == 2 { |
| 362 | release_handles(&argv); |
| 363 | return Err(VmErr::HostCallDeferred); |
| 364 | } |
| 365 | if status != 0 { |
| 366 | release_handles(&argv); |
| 367 | let (kind, msg) = with_runtime(|rt| rt.error_stash.take()) |
| 368 | .unwrap_or((ErrorKind::Runtime as u32, String::from("native call failed"))); |
| 369 | return Err(error_from_kind(kind, msg)); |
| 370 | } |
| 371 | let result = get_val(out_handle).ok_or(VmErr::Runtime("native returned invalid handle"))?; |
| 372 | argv.push(out_handle); |
| 373 | release_handles(&argv); |
| 374 | Ok(result) |
| 375 | }; |
| 376 | NativeBinding { name, func: Arc::new(closure), pure: false } |
| 377 | } |
no test coverage detected