From 1776184af13569da479898da17bb2b7213533560 Mon Sep 17 00:00:00 2001 From: zhangyuang Date: Wed, 25 Oct 2023 13:47:24 +0800 Subject: [PATCH] feat: support function as params skip ci --- cpp/sum.cpp | 2 + scripts/types.d.ts | 1 + src/ffi_macro.rs | 30 +++ src/lib.rs | 627 +++++++++++++++++++++++---------------------- src/utils.rs | 52 +++- test.ts | 1 + 6 files changed, 394 insertions(+), 319 deletions(-) create mode 100644 src/ffi_macro.rs diff --git a/cpp/sum.cpp b/cpp/sum.cpp index 07bc9f5..458769a 100644 --- a/cpp/sum.cpp +++ b/cpp/sum.cpp @@ -3,6 +3,7 @@ #include #include #include +#include extern "C" int sum(int a, int b) { return a + b; } @@ -98,6 +99,7 @@ typedef void (*FunctionPointer)(double a); extern "C" void callFunction(FunctionPointer func) { printf("callFunction"); double a = 100.11; + // bool a = false; // char *a = "Hello, World!"; // char *str = (char *)malloc(14 * sizeof(char)); // strcpy(str, "Hello, World!"); diff --git a/scripts/types.d.ts b/scripts/types.d.ts index 4071254..6132aa3 100644 --- a/scripts/types.d.ts +++ b/scripts/types.d.ts @@ -33,6 +33,7 @@ export type ArrayConstructorOptions = { export type FuncConstructorOptions = { paramsType: Array> + retType: DataFieldType } export function arrayConstructor(options: ArrayConstructorOptions): ArrayConstructorOptions diff --git a/src/ffi_macro.rs b/src/ffi_macro.rs new file mode 100644 index 0000000..0f0f920 --- /dev/null +++ b/src/ffi_macro.rs @@ -0,0 +1,30 @@ +macro_rules! match_args_len { + ($args_len:expr, $func_args_type:expr, $js_function:expr, $env:expr, $($num:literal => $closure:ident, $($arg:ident),*),*) => { + match $args_len { + $( + $num => { + use libffi::high::$closure; + let lambda = |$($arg: *mut c_void),*| { + let value: Vec = (0..$args_len) + .map(|index| { + let c_param = match index { + $( + idx if idx == index => $arg, + )* + _ => unreachable!(), + }; + let arg_type = $func_args_type.get_element::(index).unwrap(); + let param = get_js_function_call_value($env, arg_type, c_param); + param + }) + .collect(); + $js_function.call(None, &value).unwrap(); + }; + let closure = Box::into_raw(Box::new($closure::new(&lambda))); + return std::mem::transmute((*closure).code_ptr()); + } + )* + _ => panic!("func_args get array error"), + } + }; + } diff --git a/src/lib.rs b/src/lib.rs index fad67fc..1ece10f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,8 @@ #[macro_use] extern crate napi_derive; mod define; +#[macro_use] +mod ffi_macro; mod pointer; mod utils; use define::*; @@ -56,7 +58,7 @@ fn close(library: String) { } #[napi] -fn load( +unsafe fn load( env: Env, params: FFIParams, ) -> Either9, Vec, Vec, bool, JsObject> { @@ -67,112 +69,112 @@ fn load( params_type, params_value, } = params; - unsafe { - let lib = LibraryMap.as_ref().unwrap(); - let lib = lib.get(&library).unwrap(); - let func: Symbol = lib.get(func_name.as_str().as_bytes()).unwrap(); - let params_type_len = params_type.len(); - let (mut arg_types, arg_values): (Vec<*mut ffi_type>, Vec) = params_type - .into_iter() - .zip(params_value.into_iter()) - .map(|(param, value)| { - let value_type = param.get_type().unwrap(); - match value_type { - ValueType::Number => { - let param_data_type = - number_to_data_type(param.coerce_to_number().unwrap().try_into().unwrap()); - match param_data_type { - DataType::I32 => { - let arg_type = &mut ffi_type_sint32 as *mut ffi_type; - let arg_val: i32 = value.coerce_to_number().unwrap().try_into().unwrap(); - (arg_type, RsArgsValue::I32(arg_val)) - } - DataType::Double => { - let arg_type = &mut ffi_type_double as *mut ffi_type; - let arg_val: f64 = value.coerce_to_number().unwrap().try_into().unwrap(); - (arg_type, RsArgsValue::Double(arg_val)) - } - DataType::String => { - let arg_type = &mut ffi_type_pointer as *mut ffi_type; - let arg_val: String = value - .coerce_to_string() - .unwrap() - .into_utf8() - .unwrap() - .try_into() - .unwrap(); - (arg_type, RsArgsValue::String(arg_val)) - } - DataType::I32Array => { - let arg_type = &mut ffi_type_pointer as *mut ffi_type; - let js_object = value.coerce_to_object().unwrap(); - let arg_val = vec![0; js_object.get_array_length().unwrap() as usize] - .iter() - .enumerate() - .map(|(index, _)| { - let js_element: JsNumber = js_object.get_element(index as u32).unwrap(); - return js_element.get_int32().unwrap(); - }) - .collect::>(); + let lib = LibraryMap.as_ref().unwrap(); + let lib = lib.get(&library).unwrap(); + let func: Symbol = lib.get(func_name.as_str().as_bytes()).unwrap(); + let params_type_len = params_type.len(); + let (mut arg_types, arg_values): (Vec<*mut ffi_type>, Vec) = params_type + .into_iter() + .zip(params_value.into_iter()) + .map(|(param, value)| { + let value_type = param.get_type().unwrap(); + match value_type { + ValueType::Number => { + let param_data_type = + number_to_data_type(param.coerce_to_number().unwrap().try_into().unwrap()); + match param_data_type { + DataType::I32 => { + let arg_type = &mut ffi_type_sint32 as *mut ffi_type; + let arg_val: i32 = value.coerce_to_number().unwrap().try_into().unwrap(); + (arg_type, RsArgsValue::I32(arg_val)) + } + DataType::Double => { + let arg_type = &mut ffi_type_double as *mut ffi_type; + let arg_val: f64 = value.coerce_to_number().unwrap().try_into().unwrap(); + (arg_type, RsArgsValue::Double(arg_val)) + } + DataType::String => { + let arg_type = &mut ffi_type_pointer as *mut ffi_type; + let arg_val: String = value + .coerce_to_string() + .unwrap() + .into_utf8() + .unwrap() + .try_into() + .unwrap(); + (arg_type, RsArgsValue::String(arg_val)) + } + DataType::I32Array => { + let arg_type = &mut ffi_type_pointer as *mut ffi_type; + let js_object = value.coerce_to_object().unwrap(); + let arg_val = vec![0; js_object.get_array_length().unwrap() as usize] + .iter() + .enumerate() + .map(|(index, _)| { + let js_element: JsNumber = js_object.get_element(index as u32).unwrap(); + return js_element.get_int32().unwrap(); + }) + .collect::>(); - (arg_type, RsArgsValue::I32Array(arg_val)) - } - DataType::DoubleArray => { - let arg_type = &mut ffi_type_pointer as *mut ffi_type; - let js_object = value.coerce_to_object().unwrap(); - let arg_val = vec![0; js_object.get_array_length().unwrap() as usize] - .iter() - .enumerate() - .map(|(index, _)| { - let js_element: JsNumber = js_object.get_element(index as u32).unwrap(); - return js_element.get_double().unwrap(); - }) - .collect::>(); + (arg_type, RsArgsValue::I32Array(arg_val)) + } + DataType::DoubleArray => { + let arg_type = &mut ffi_type_pointer as *mut ffi_type; + let js_object = value.coerce_to_object().unwrap(); + let arg_val = vec![0; js_object.get_array_length().unwrap() as usize] + .iter() + .enumerate() + .map(|(index, _)| { + let js_element: JsNumber = js_object.get_element(index as u32).unwrap(); + return js_element.get_double().unwrap(); + }) + .collect::>(); - (arg_type, RsArgsValue::DoubleArray(arg_val)) - } - DataType::StringArray => { - let arg_type = &mut ffi_type_pointer as *mut ffi_type; - let js_object = value.coerce_to_object().unwrap(); - let arg_val = js_array_to_string_array(js_object); - (arg_type, RsArgsValue::StringArray(arg_val)) - } - DataType::Boolean => { - let arg_type = &mut ffi_type_uint8 as *mut ffi_type; - let arg_val: bool = value.coerce_to_bool().unwrap().get_value().unwrap(); - (arg_type, RsArgsValue::Boolean(arg_val)) - } - DataType::Void => { - let arg_type = &mut ffi_type_void as *mut ffi_type; - (arg_type, RsArgsValue::Void(())) - } - _ => panic!(""), + (arg_type, RsArgsValue::DoubleArray(arg_val)) } + DataType::StringArray => { + let arg_type = &mut ffi_type_pointer as *mut ffi_type; + let js_object = value.coerce_to_object().unwrap(); + let arg_val = js_array_to_string_array(js_object); + (arg_type, RsArgsValue::StringArray(arg_val)) + } + DataType::Boolean => { + let arg_type = &mut ffi_type_uint8 as *mut ffi_type; + let arg_val: bool = value.coerce_to_bool().unwrap().get_value().unwrap(); + (arg_type, RsArgsValue::Boolean(arg_val)) + } + DataType::Void => { + let arg_type = &mut ffi_type_void as *mut ffi_type; + (arg_type, RsArgsValue::Void(())) + } + _ => panic!(""), } - ValueType::Object => { - let params_type_object: JsObject = param.coerce_to_object().unwrap(); - let arg_type = &mut ffi_type_pointer as *mut ffi_type; - let params_value_object = value.coerce_to_object().unwrap(); - let index_map = jsobject_to_rs_struct(params_type_object, params_value_object); - (arg_type, RsArgsValue::Object(index_map)) - } - ValueType::Function => { - let params_type_function: JsFunction = param.try_into().unwrap(); - let params_val_function: JsFunction = value.try_into().unwrap(); - let arg_type = &mut ffi_type_pointer as *mut ffi_type; - ( - arg_type, - RsArgsValue::Function(params_type_function, params_val_function), - ) - } - _ => panic!("unknow params type"), } - }) - .unzip(); + ValueType::Object => { + let params_type_object: JsObject = param.coerce_to_object().unwrap(); + let arg_type = &mut ffi_type_pointer as *mut ffi_type; + let params_value_object = value.coerce_to_object().unwrap(); + let index_map = jsobject_to_rs_struct(params_type_object, params_value_object); + (arg_type, RsArgsValue::Object(index_map)) + } + ValueType::Function => { + let params_type_function: JsFunction = param.try_into().unwrap(); + let params_val_function: JsFunction = value.try_into().unwrap(); + let arg_type = &mut ffi_type_pointer as *mut ffi_type; + ( + arg_type, + RsArgsValue::Function(params_type_function, params_val_function), + ) + } + _ => panic!("unknow params type"), + } + }) + .unzip(); - let mut arg_values_c_void: Vec<*mut c_void> = arg_values - .into_iter() - .map(|val| match val { + let mut arg_values_c_void: Vec<*mut c_void> = arg_values + .into_iter() + .map(|val| { + match val { RsArgsValue::I32(val) => { let c_num = Box::new(val); Box::into_raw(c_num) as *mut c_void @@ -226,28 +228,29 @@ fn load( .coerce_to_object() .unwrap(); - let func_args: JsObject = func_desc_obj.get_named_property("paramsType").unwrap(); - match func_args.get_array_length().unwrap() { - 0 => { - use libffi::high::Closure0; - let lambda = || { - js_function.call_without_args(None).unwrap(); - }; - let closure = Box::into_raw(Box::new(Closure0::new(&lambda))); - return std::mem::transmute((*closure).code_ptr()); - } - 1 => { - use libffi::high::{CType, Closure1}; - let lambda = |a: *mut c_void| { - // let value = func_args.get_element::(0).unwrap(); - // let param1 = get_js_function_call_value(env, value, a); - // js_function.call(None, &[param1]).unwrap(); - }; - let closure = Box::into_raw(Box::new(Closure1::new(&lambda))); - return std::mem::transmute((*closure).code_ptr()); - } - _ => panic!("func_args get array error"), - }; + let func_args_type: JsObject = func_desc_obj.get_named_property("paramsType").unwrap(); + let args_len = func_args_type.get_array_length().unwrap(); + if args_len == 0 { + use libffi::high::Closure0; + let lambda = || { + js_function.call_without_args(None).unwrap(); + }; + let closure = Box::into_raw(Box::new(Closure0::new(&lambda))); + return std::mem::transmute((*closure).code_ptr()); + } + + match_args_len!(args_len, func_args_type, js_function, env, + 1 => Closure1, a, + 2 => Closure2, a,b, + 3 => Closure3, a,b,c, + 4 => Closure4, a,b,c,d, + 5 => Closure5, a,b,c,d,e, + 6 => Closure6, a,b,c,d,e,f, + 7 => Closure7, a,b,c,d,e,f,g, + 8 => Closure8, a,b,c,d,e,f,g,h, + 9 => Closure9, a,b,c,d,e,f,g,h,i, + 10 => Closure10, a,b,c,d,e,f,g,h,i,j + ) } RsArgsValue::Object(val) => { let (size, _) = calculate_layout(&val); @@ -345,215 +348,213 @@ fn load( let p = Box::into_raw(Box::new(ptr)) as *mut c_void; return p; } - }) - .collect(); - - let ret_value_type = ret_type.get_type().unwrap(); - let ret_value: FFIJsValue = match ret_value_type { - ValueType::Number => { - FFIJsValue::I32(ret_type.coerce_to_number().unwrap().try_into().unwrap()) } - ValueType::Object => FFIJsValue::JsObject(ret_type.coerce_to_object().unwrap()), - _ => FFIJsValue::Unknown, - }; - let r_type: *mut ffi_type = match ret_value { - FFIJsValue::I32(number) => { - let ret_data_type = number_to_data_type(number); - match ret_data_type { - DataType::I32 => &mut ffi_type_sint32 as *mut ffi_type, - DataType::String => &mut ffi_type_pointer as *mut ffi_type, - DataType::Void => &mut ffi_type_void as *mut ffi_type, - DataType::Double => &mut ffi_type_double as *mut ffi_type, - DataType::I32Array => &mut ffi_type_pointer as *mut ffi_type, - DataType::StringArray => &mut ffi_type_pointer as *mut ffi_type, - DataType::DoubleArray => &mut ffi_type_pointer as *mut ffi_type, - DataType::Boolean => &mut ffi_type_uint8 as *mut ffi_type, - } + }) + .collect(); + + let ret_value_type = ret_type.get_type().unwrap(); + let ret_value: FFIJsValue = match ret_value_type { + ValueType::Number => FFIJsValue::I32(ret_type.coerce_to_number().unwrap().try_into().unwrap()), + ValueType::Object => FFIJsValue::JsObject(ret_type.coerce_to_object().unwrap()), + _ => FFIJsValue::Unknown, + }; + let r_type: *mut ffi_type = match ret_value { + FFIJsValue::I32(number) => { + let ret_data_type = number_to_data_type(number); + match ret_data_type { + DataType::I32 => &mut ffi_type_sint32 as *mut ffi_type, + DataType::String => &mut ffi_type_pointer as *mut ffi_type, + DataType::Void => &mut ffi_type_void as *mut ffi_type, + DataType::Double => &mut ffi_type_double as *mut ffi_type, + DataType::I32Array => &mut ffi_type_pointer as *mut ffi_type, + DataType::StringArray => &mut ffi_type_pointer as *mut ffi_type, + DataType::DoubleArray => &mut ffi_type_pointer as *mut ffi_type, + DataType::Boolean => &mut ffi_type_uint8 as *mut ffi_type, } - FFIJsValue::JsObject(_) => &mut ffi_type_pointer as *mut ffi_type, - FFIJsValue::Unknown => &mut ffi_type_void as *mut ffi_type, - }; + } + FFIJsValue::JsObject(_) => &mut ffi_type_pointer as *mut ffi_type, + FFIJsValue::Unknown => &mut ffi_type_void as *mut ffi_type, + }; - let mut cif = ffi_cif { - abi: ffi_abi_FFI_DEFAULT_ABI, - nargs: params_type_len as u32, - arg_types: arg_types.as_mut_ptr(), - rtype: r_type, - bytes: 0, - flags: 0, - #[cfg(all(target_arch = "aarch64", target_vendor = "apple"))] - aarch64_nfixedargs: params_type_len as u32, - }; + let mut cif = ffi_cif { + abi: ffi_abi_FFI_DEFAULT_ABI, + nargs: params_type_len as u32, + arg_types: arg_types.as_mut_ptr(), + rtype: r_type, + bytes: 0, + flags: 0, + #[cfg(all(target_arch = "aarch64", target_vendor = "apple"))] + aarch64_nfixedargs: params_type_len as u32, + }; - ffi_prep_cif( - &mut cif as *mut ffi_cif, - ffi_abi_FFI_DEFAULT_ABI, - params_type_len as u32, - r_type, - arg_types.as_mut_ptr(), - ); - match ret_value { - FFIJsValue::I32(number) => { - let ret_data_type = number_to_data_type(number); - match ret_data_type { - DataType::String => { - let mut result: *mut c_char = malloc(std::mem::size_of::<*mut c_char>()) as *mut c_char; - ffi_call( - &mut cif, - Some(*func), - &mut result as *mut *mut c_char as *mut c_void, - arg_values_c_void.as_mut_ptr(), - ); + ffi_prep_cif( + &mut cif as *mut ffi_cif, + ffi_abi_FFI_DEFAULT_ABI, + params_type_len as u32, + r_type, + arg_types.as_mut_ptr(), + ); + match ret_value { + FFIJsValue::I32(number) => { + let ret_data_type = number_to_data_type(number); + match ret_data_type { + DataType::String => { + let mut result: *mut c_char = malloc(std::mem::size_of::<*mut c_char>()) as *mut c_char; + ffi_call( + &mut cif, + Some(*func), + &mut result as *mut *mut c_char as *mut c_void, + arg_values_c_void.as_mut_ptr(), + ); - let result_str = CString::from_raw(result) - .into_string() - .expect(format!("{} retType is not string", func_name).as_str()); + let result_str = CString::from_raw(result) + .into_string() + .expect(format!("{} retType is not string", func_name).as_str()); - Either9::A(result_str) - } - DataType::I32 => { - let mut result: i32 = 0; - ffi_call( - &mut cif, - Some(*func), - &mut result as *mut i32 as *mut c_void, - arg_values_c_void.as_mut_ptr(), - ); - Either9::B(result) - } - DataType::Void => { - let mut result = (); - ffi_call( - &mut cif, - Some(*func), - &mut result as *mut () as *mut c_void, - arg_values_c_void.as_mut_ptr(), - ); - Either9::C(()) - } - DataType::Double => { - let mut result: f64 = 0.0; - ffi_call( - &mut cif, - Some(*func), - &mut result as *mut f64 as *mut c_void, - arg_values_c_void.as_mut_ptr(), - ); - Either9::D(result) - } - DataType::Boolean => { - let mut result: bool = false; - ffi_call( - &mut cif, - Some(*func), - &mut result as *mut bool as *mut c_void, - arg_values_c_void.as_mut_ptr(), - ); + Either9::A(result_str) + } + DataType::I32 => { + let mut result: i32 = 0; + ffi_call( + &mut cif, + Some(*func), + &mut result as *mut i32 as *mut c_void, + arg_values_c_void.as_mut_ptr(), + ); + Either9::B(result) + } + DataType::Void => { + let mut result = (); + ffi_call( + &mut cif, + Some(*func), + &mut result as *mut () as *mut c_void, + arg_values_c_void.as_mut_ptr(), + ); + Either9::C(()) + } + DataType::Double => { + let mut result: f64 = 0.0; + ffi_call( + &mut cif, + Some(*func), + &mut result as *mut f64 as *mut c_void, + arg_values_c_void.as_mut_ptr(), + ); + Either9::D(result) + } + DataType::Boolean => { + let mut result: bool = false; + ffi_call( + &mut cif, + Some(*func), + &mut result as *mut bool as *mut c_void, + arg_values_c_void.as_mut_ptr(), + ); - Either9::H(result) - } - _ => { - panic!( - "{:?} is not currently avaiable as a return type", - ret_data_type - ) - } + Either9::H(result) + } + _ => { + panic!( + "{:?} is not currently avaiable as a return type", + ret_data_type + ) } } - FFIJsValue::JsObject(ret_object) => { - let ffi_tag = ret_object.has_named_property("ffiTypeTag").unwrap(); - if ffi_tag { - let ffi_tag: &str = &js_string_to_string( - ret_object - .get_named_property::("ffiTypeTag") - .unwrap(), - ); - match ffi_tag { - "array" => { - let array_len: usize = - js_nunmber_to_i32(ret_object.get_named_property::("length").unwrap()) - as usize; + } + FFIJsValue::JsObject(ret_object) => { + let ffi_tag = ret_object.has_named_property("ffiTypeTag").unwrap(); + if ffi_tag { + let ffi_tag: &str = &js_string_to_string( + ret_object + .get_named_property::("ffiTypeTag") + .unwrap(), + ); + match ffi_tag { + "array" => { + let array_len: usize = + js_nunmber_to_i32(ret_object.get_named_property::("length").unwrap()) + as usize; - let array_type: i32 = - js_nunmber_to_i32(ret_object.get_named_property::("type").unwrap()); - let array_type = number_to_data_type(array_type); - match array_type { - DataType::I32Array => { - let mut result: *mut c_int = - malloc(std::mem::size_of::<*mut c_int>()) as *mut c_int; - ffi_call( - &mut cif, - Some(*func), - &mut result as *mut _ as *mut c_void, - arg_values_c_void.as_mut_ptr(), - ); - let arr = create_array_from_pointer(result, array_len); - if !result.is_null() { - libc::free(result as *mut c_void); - } - Either9::E(arr) + let array_type: i32 = + js_nunmber_to_i32(ret_object.get_named_property::("type").unwrap()); + let array_type = number_to_data_type(array_type); + match array_type { + DataType::I32Array => { + let mut result: *mut c_int = + malloc(std::mem::size_of::<*mut c_int>()) as *mut c_int; + ffi_call( + &mut cif, + Some(*func), + &mut result as *mut _ as *mut c_void, + arg_values_c_void.as_mut_ptr(), + ); + let arr = create_array_from_pointer(result, array_len); + if !result.is_null() { + libc::free(result as *mut c_void); } - DataType::DoubleArray => { - let mut result: *mut c_double = - malloc(std::mem::size_of::<*mut c_double>()) as *mut c_double; - ffi_call( - &mut cif, - Some(*func), - &mut result as *mut _ as *mut c_void, - arg_values_c_void.as_mut_ptr(), - ); - let arr = create_array_from_pointer(result, array_len); - if !result.is_null() { - libc::free(result as *mut c_void); - } - Either9::G(arr) + Either9::E(arr) + } + DataType::DoubleArray => { + let mut result: *mut c_double = + malloc(std::mem::size_of::<*mut c_double>()) as *mut c_double; + ffi_call( + &mut cif, + Some(*func), + &mut result as *mut _ as *mut c_void, + arg_values_c_void.as_mut_ptr(), + ); + let arr = create_array_from_pointer(result, array_len); + if !result.is_null() { + libc::free(result as *mut c_void); } - DataType::StringArray => { - let mut result: *mut *mut c_char = - malloc(std::mem::size_of::<*mut *mut c_char>()) as *mut *mut c_char; + Either9::G(arr) + } + DataType::StringArray => { + let mut result: *mut *mut c_char = + malloc(std::mem::size_of::<*mut *mut c_char>()) as *mut *mut c_char; - ffi_call( - &mut cif, - Some(*func), - &mut result as *mut _ as *mut c_void, - arg_values_c_void.as_mut_ptr(), - ); - let arr = create_array_from_pointer(result, array_len); - if !result.is_null() { - libc::free(result as *mut c_void); - } - Either9::F(arr) + ffi_call( + &mut cif, + Some(*func), + &mut result as *mut _ as *mut c_void, + arg_values_c_void.as_mut_ptr(), + ); + let arr = create_array_from_pointer(result, array_len); + if !result.is_null() { + libc::free(result as *mut c_void); } - _ => panic!("some error"), + Either9::F(arr) } + _ => panic!("some error"), } - _ => panic!("some error"), } - } else { - let ret_fields_size = - JsObject::keys(&ret_object) - .unwrap() - .into_iter() - .fold(0, |pre, current| { - let size = pre; - let val: JsUnknown = ret_object.get_named_property(¤t).unwrap(); - let data_type = js_unknown_to_data_type(val); - let (field_size, _) = get_data_type_size_align(data_type); - size + field_size - }); - let mut result: *mut c_void = malloc(ret_fields_size); - ffi_call( - &mut cif, - Some(*func), - &mut result as *mut _ as *mut c_void, - arg_values_c_void.as_mut_ptr(), - ); - let js_object = create_object_from_pointer(env, result, ret_object); - Either9::I(js_object) + _ => panic!("some error"), } + } else { + let ret_fields_size = + JsObject::keys(&ret_object) + .unwrap() + .into_iter() + .fold(0, |pre, current| { + let size = pre; + let val: JsUnknown = ret_object.get_named_property(¤t).unwrap(); + let data_type = js_unknown_to_data_type(val); + let (field_size, _) = get_data_type_size_align(data_type); + size + field_size + }); + let mut result: *mut c_void = malloc(ret_fields_size); + ffi_call( + &mut cif, + Some(*func), + &mut result as *mut _ as *mut c_void, + arg_values_c_void.as_mut_ptr(), + ); + let js_object = create_object_from_pointer(env, result, ret_object); + Either9::I(js_object) } - - FFIJsValue::Unknown => Either9::C(()), } + + FFIJsValue::Unknown => Either9::C(()), } } diff --git a/src/utils.rs b/src/utils.rs index 4d1484a..740a1ae 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,14 +1,14 @@ use crate::define::{number_to_data_type, DataType, RsArgsValue}; +use crate::pointer::{create_array_from_pointer, create_object_from_pointer}; use indexmap::IndexMap; use napi::bindgen_prelude::*; use napi::{JsBoolean, JsNumber, JsObject, JsString, JsUnknown}; use std::ffi::c_void; use std::ffi::{c_char, c_double, c_int, CString}; -use std::mem::{transmute, transmute_copy}; pub unsafe fn get_js_function_call_value( env: Env, func_arg_type: JsUnknown, - func_arg_val: *mut c_void, + func_arg_ptr: *mut c_void, ) -> JsUnknown { return match func_arg_type.get_type().unwrap() { ValueType::Number => { @@ -21,13 +21,21 @@ pub unsafe fn get_js_function_call_value( ); let data = match data_type { DataType::I32 => env - .create_int32(func_arg_val as i32) + .create_int32(func_arg_ptr as i32) + .unwrap() + .into_unknown(), + DataType::Boolean => env + .get_boolean(if func_arg_ptr as i32 == 0 { + false + } else { + true + }) .unwrap() .into_unknown(), DataType::String => { return env .create_string( - &CString::from_raw(func_arg_val as *mut c_char) + &CString::from_raw(func_arg_ptr as *mut c_char) .into_string() .unwrap(), ) @@ -35,13 +43,45 @@ pub unsafe fn get_js_function_call_value( .into_unknown(); } DataType::Double => { - println!("{:?}", func_arg_val); + println!("{:?}", func_arg_ptr); return env.create_double(1.1).unwrap().into_unknown(); } - _ => panic!("get_js_function_call_value err"), + _ => panic!( + "{:?} data_type as function args is unsupported at this time", + data_type + ), }; data } + ValueType::Object => { + let args_type = func_arg_type.coerce_to_object().unwrap(); + let ffi_tag = args_type.has_named_property("ffiTypeTag").unwrap(); + if ffi_tag { + let array_len: usize = + js_nunmber_to_i32(args_type.get_named_property::("length").unwrap()) as usize; + let array_type: i32 = + js_nunmber_to_i32(args_type.get_named_property::("type").unwrap()); + let array_type = number_to_data_type(array_type); + + match array_type { + DataType::StringArray => { + let arr = create_array_from_pointer(func_arg_ptr as *mut *mut c_char, array_len); + rs_array_to_js_array(env, ArrayType::String(arr)).into_unknown() + } + DataType::I32Array => { + let arr = create_array_from_pointer(func_arg_ptr as *mut c_int, array_len); + rs_array_to_js_array(env, ArrayType::I32(arr)).into_unknown() + } + DataType::DoubleArray => { + let arr = create_array_from_pointer(func_arg_ptr as *mut c_double, array_len); + rs_array_to_js_array(env, ArrayType::Double(arr)).into_unknown() + } + _ => panic!("{:?} as function args is unsupported ", array_type), + } + } else { + create_object_from_pointer(env, func_arg_ptr, args_type).into_unknown() + } + } _ => panic!("get_js_function_call_value err "), }; } diff --git a/test.ts b/test.ts index 4e76e97..2662e4f 100644 --- a/test.ts +++ b/test.ts @@ -161,6 +161,7 @@ const unitTest = () => { retType: DataType.Void, paramsType: [funcConstructor({ paramsType: [DataType.Double], + retType: DataType.Void })], paramsValue: [func], })