diff options
author | Dj <43033058+DjDeveloperr@users.noreply.github.com> | 2023-01-07 19:58:10 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-08 09:28:10 +0530 |
commit | ad82918f56b215a428ebe7c533ee825e1152d1b4 (patch) | |
tree | 2669f9d8d419a88e9d58b12b98579e884aec6988 /ext/ffi/dlfcn.rs | |
parent | 84ef26ac9b5f0e1199d77837cd97cb203baa8729 (diff) |
feat(ext/ffi): structs by value (#15060)
Adds support for passing and returning structs as buffers to FFI. This does not implement fastapi support for structs. Needed for certain system APIs such as AppKit on macOS.
Diffstat (limited to 'ext/ffi/dlfcn.rs')
-rw-r--r-- | ext/ffi/dlfcn.rs | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/ext/ffi/dlfcn.rs b/ext/ffi/dlfcn.rs index 5caf95ef2..eeff2c8a7 100644 --- a/ext/ffi/dlfcn.rs +++ b/ext/ffi/dlfcn.rs @@ -1,6 +1,7 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. use crate::check_unstable; +use crate::ir::out_buffer_as_ptr; use crate::symbol::NativeType; use crate::symbol::Symbol; use crate::turbocall; @@ -52,7 +53,7 @@ impl DynamicLibraryResource { } } -pub fn needs_unwrap(rv: NativeType) -> bool { +pub fn needs_unwrap(rv: &NativeType) -> bool { matches!( rv, NativeType::Function @@ -65,7 +66,7 @@ pub fn needs_unwrap(rv: NativeType) -> bool { ) } -fn is_i64(rv: NativeType) -> bool { +fn is_i64(rv: &NativeType) -> bool { matches!(rv, NativeType::I64 | NativeType::ISize) } @@ -166,7 +167,7 @@ where .clone() .into_iter() .map(libffi::middle::Type::from), - foreign_fn.result.into(), + foreign_fn.result.clone().into(), ); let func_key = v8::String::new(scope, &symbol_key).unwrap(); @@ -216,11 +217,24 @@ fn make_sync_fn<'s>( // SAFETY: The pointer will not be deallocated until the function is // garbage collected. let symbol = unsafe { &*(external.value() as *const Symbol) }; - let needs_unwrap = match needs_unwrap(symbol.result_type) { + let needs_unwrap = match needs_unwrap(&symbol.result_type) { true => Some(args.get(symbol.parameter_types.len() as i32)), false => None, }; - match crate::call::ffi_call_sync(scope, args, symbol) { + let out_buffer = match symbol.result_type { + NativeType::Struct(_) => { + let argc = args.length(); + out_buffer_as_ptr( + scope, + Some( + v8::Local::<v8::TypedArray>::try_from(args.get(argc - 1)) + .unwrap(), + ), + ) + } + _ => None, + }; + match crate::call::ffi_call_sync(scope, args, symbol, out_buffer) { Ok(result) => { match needs_unwrap { Some(v) => { @@ -228,7 +242,7 @@ fn make_sync_fn<'s>( let backing_store = view.buffer(scope).unwrap().get_backing_store(); - if is_i64(symbol.result_type) { + if is_i64(&symbol.result_type) { // SAFETY: v8::SharedRef<v8::BackingStore> is similar to Arc<[u8]>, // it points to a fixed continuous slice of bytes on the heap. let bs = unsafe { @@ -251,8 +265,9 @@ fn make_sync_fn<'s>( } } None => { - // SAFETY: Same return type declared to libffi; trust user to have it right beyond that. - let result = unsafe { result.to_v8(scope, symbol.result_type) }; + let result = + // SAFETY: Same return type declared to libffi; trust user to have it right beyond that. + unsafe { result.to_v8(scope, symbol.result_type.clone()) }; rv.set(result.v8_value); } } |