diff options
Diffstat (limited to 'ext/ffi/call.rs')
-rw-r--r-- | ext/ffi/call.rs | 140 |
1 files changed, 75 insertions, 65 deletions
diff --git a/ext/ffi/call.rs b/ext/ffi/call.rs index 731460af9..8a9b393c3 100644 --- a/ext/ffi/call.rs +++ b/ext/ffi/call.rs @@ -14,9 +14,11 @@ use deno_core::error::AnyError; use deno_core::op; use deno_core::serde_json::Value; use deno_core::serde_v8; +use deno_core::serde_v8::ExternalPointer; use deno_core::v8; use deno_core::ResourceId; use libffi::middle::Arg; +use serde::Serialize; use std::cell::RefCell; use std::ffi::c_void; use std::future::Future; @@ -28,14 +30,13 @@ unsafe fn ffi_call_rtype_struct( fn_ptr: &libffi::middle::CodePtr, call_args: Vec<Arg>, out_buffer: *mut u8, -) -> NativeValue { +) { libffi::raw::ffi_call( cif.as_raw_ptr(), Some(*fn_ptr.as_safe_fun()), out_buffer as *mut c_void, call_args.as_ptr() as *mut *mut c_void, ); - NativeValue { void_value: () } } // A one-off synchronous FFI call. @@ -174,16 +175,25 @@ where pointer: cif.call::<*mut c_void>(*fun_ptr, &call_args), } } - NativeType::Struct(_) => ffi_call_rtype_struct( - &symbol.cif, - &symbol.ptr, - call_args, - out_buffer.unwrap().0, - ), + NativeType::Struct(_) => NativeValue { + void_value: ffi_call_rtype_struct( + &symbol.cif, + &symbol.ptr, + call_args, + out_buffer.unwrap().0, + ), + }, }) } } +#[derive(Serialize)] +#[serde(untagged)] +pub enum FfiValue { + Value(Value), + External(ExternalPointer), +} + fn ffi_call( call_args: Vec<NativeValue>, cif: &libffi::middle::Cif, @@ -191,7 +201,7 @@ fn ffi_call( parameter_types: &[NativeType], result_type: NativeType, out_buffer: Option<OutBuffer>, -) -> Result<NativeValue, AnyError> { +) -> Result<FfiValue, AnyError> { let call_args: Vec<Arg> = call_args .iter() .enumerate() @@ -205,55 +215,57 @@ fn ffi_call( // types of symbol. unsafe { Ok(match result_type { - NativeType::Void => NativeValue { - void_value: cif.call::<()>(fun_ptr, &call_args), - }, - NativeType::Bool => NativeValue { - bool_value: cif.call::<bool>(fun_ptr, &call_args), - }, - NativeType::U8 => NativeValue { - u8_value: cif.call::<u8>(fun_ptr, &call_args), - }, - NativeType::I8 => NativeValue { - i8_value: cif.call::<i8>(fun_ptr, &call_args), - }, - NativeType::U16 => NativeValue { - u16_value: cif.call::<u16>(fun_ptr, &call_args), - }, - NativeType::I16 => NativeValue { - i16_value: cif.call::<i16>(fun_ptr, &call_args), - }, - NativeType::U32 => NativeValue { - u32_value: cif.call::<u32>(fun_ptr, &call_args), - }, - NativeType::I32 => NativeValue { - i32_value: cif.call::<i32>(fun_ptr, &call_args), - }, - NativeType::U64 => NativeValue { - u64_value: cif.call::<u64>(fun_ptr, &call_args), - }, - NativeType::I64 => NativeValue { - i64_value: cif.call::<i64>(fun_ptr, &call_args), - }, - NativeType::USize => NativeValue { - usize_value: cif.call::<usize>(fun_ptr, &call_args), - }, - NativeType::ISize => NativeValue { - isize_value: cif.call::<isize>(fun_ptr, &call_args), - }, - NativeType::F32 => NativeValue { - f32_value: cif.call::<f32>(fun_ptr, &call_args), - }, - NativeType::F64 => NativeValue { - f64_value: cif.call::<f64>(fun_ptr, &call_args), - }, + NativeType::Void => { + cif.call::<()>(fun_ptr, &call_args); + FfiValue::Value(Value::from(())) + } + NativeType::Bool => { + FfiValue::Value(Value::from(cif.call::<bool>(fun_ptr, &call_args))) + } + NativeType::U8 => { + FfiValue::Value(Value::from(cif.call::<u8>(fun_ptr, &call_args))) + } + NativeType::I8 => { + FfiValue::Value(Value::from(cif.call::<i8>(fun_ptr, &call_args))) + } + NativeType::U16 => { + FfiValue::Value(Value::from(cif.call::<u16>(fun_ptr, &call_args))) + } + NativeType::I16 => { + FfiValue::Value(Value::from(cif.call::<i16>(fun_ptr, &call_args))) + } + NativeType::U32 => { + FfiValue::Value(Value::from(cif.call::<u32>(fun_ptr, &call_args))) + } + NativeType::I32 => { + FfiValue::Value(Value::from(cif.call::<i32>(fun_ptr, &call_args))) + } + NativeType::U64 => { + FfiValue::Value(Value::from(cif.call::<u64>(fun_ptr, &call_args))) + } + NativeType::I64 => { + FfiValue::Value(Value::from(cif.call::<i64>(fun_ptr, &call_args))) + } + NativeType::USize => { + FfiValue::Value(Value::from(cif.call::<usize>(fun_ptr, &call_args))) + } + NativeType::ISize => { + FfiValue::Value(Value::from(cif.call::<isize>(fun_ptr, &call_args))) + } + NativeType::F32 => { + FfiValue::Value(Value::from(cif.call::<f32>(fun_ptr, &call_args))) + } + NativeType::F64 => { + FfiValue::Value(Value::from(cif.call::<f64>(fun_ptr, &call_args))) + } NativeType::Pointer | NativeType::Function | NativeType::Buffer => { - NativeValue { - pointer: cif.call::<*mut c_void>(fun_ptr, &call_args), - } + FfiValue::External(ExternalPointer::from( + cif.call::<*mut c_void>(fun_ptr, &call_args), + )) } NativeType::Struct(_) => { - ffi_call_rtype_struct(cif, &fun_ptr, call_args, out_buffer.unwrap().0) + ffi_call_rtype_struct(cif, &fun_ptr, call_args, out_buffer.unwrap().0); + FfiValue::Value(Value::Null) } }) } @@ -263,11 +275,11 @@ fn ffi_call( pub fn op_ffi_call_ptr_nonblocking<'scope, FP>( scope: &mut v8::HandleScope<'scope>, state: Rc<RefCell<deno_core::OpState>>, - pointer: usize, + pointer: *mut c_void, def: ForeignFunction, parameters: serde_v8::Value<'scope>, out_buffer: Option<serde_v8::Value<'scope>>, -) -> Result<impl Future<Output = Result<Value, AnyError>>, AnyError> +) -> Result<impl Future<Output = Result<FfiValue, AnyError>>, AnyError> where FP: FfiPermissions + 'static, { @@ -280,7 +292,6 @@ where let symbol = PtrSymbol::new(pointer, &def)?; let call_args = ffi_parse_args(scope, parameters, &def.parameters)?; - let def_result = def.result.clone(); let out_buffer = out_buffer .map(|v| v8::Local::<v8::TypedArray>::try_from(v.v8_value).unwrap()); @@ -303,7 +314,7 @@ where .await .map_err(|err| anyhow!("Nonblocking FFI call failed: {}", err))??; // SAFETY: Same return type declared to libffi; trust user to have it right beyond that. - Ok(unsafe { result.to_value(def_result) }) + Ok(result) }) } @@ -316,7 +327,8 @@ pub fn op_ffi_call_nonblocking<'scope>( symbol: String, parameters: serde_v8::Value<'scope>, out_buffer: Option<serde_v8::Value<'scope>>, -) -> Result<impl Future<Output = Result<Value, AnyError>> + 'static, AnyError> { +) -> Result<impl Future<Output = Result<FfiValue, AnyError>> + 'static, AnyError> +{ let symbol = { let state = state.borrow(); let resource = state.resource_table.get::<DynamicLibraryResource>(rid)?; @@ -332,7 +344,6 @@ pub fn op_ffi_call_nonblocking<'scope>( .map(|v| v8::Local::<v8::TypedArray>::try_from(v.v8_value).unwrap()); let out_buffer_ptr = out_buffer_as_ptr(scope, out_buffer); - let result_type = symbol.result_type.clone(); let join_handle = tokio::task::spawn_blocking(move || { let Symbol { cif, @@ -356,7 +367,7 @@ pub fn op_ffi_call_nonblocking<'scope>( .await .map_err(|err| anyhow!("Nonblocking FFI call failed: {}", err))??; // SAFETY: Same return type declared to libffi; trust user to have it right beyond that. - Ok(unsafe { result.to_value(result_type) }) + Ok(result) }) } @@ -364,11 +375,11 @@ pub fn op_ffi_call_nonblocking<'scope>( pub fn op_ffi_call_ptr<FP, 'scope>( scope: &mut v8::HandleScope<'scope>, state: Rc<RefCell<deno_core::OpState>>, - pointer: usize, + pointer: *mut c_void, def: ForeignFunction, parameters: serde_v8::Value<'scope>, out_buffer: Option<serde_v8::Value<'scope>>, -) -> Result<serde_v8::Value<'scope>, AnyError> +) -> Result<FfiValue, AnyError> where FP: FfiPermissions + 'static, { @@ -395,6 +406,5 @@ where out_buffer_ptr, )?; // SAFETY: Same return type declared to libffi; trust user to have it right beyond that. - let result = unsafe { result.to_v8(scope, def.result) }; Ok(result) } |