From 5002088240776e68199a6afb5cd4c48dc3f7da16 Mon Sep 17 00:00:00 2001 From: qwreey Date: Mon, 21 Oct 2024 15:10:12 +0000 Subject: [PATCH] Fix closure error (#243) --- crates/lune-std-ffi/README.md | 38 +++++++-------- crates/lune-std-ffi/src/c/fn_info.rs | 2 +- crates/lune-std-ffi/src/data/callable_data.rs | 12 ----- crates/lune-std-ffi/src/data/closure_data.rs | 47 ++++--------------- tests/ffi/README.md | 20 ++++---- tests/ffi/external-closure/lib.c | 14 ------ .../init.luau | 22 +++++++-- tests/ffi/external_closure/lib.c | 12 +++++ .../init.luau | 2 +- .../{external-math => external_math}/lib.c | 0 .../init.luau | 12 ++--- .../lib.c | 0 .../init.luau | 2 +- .../{external-print => external_print}/lib.c | 0 .../init.luau | 2 +- .../lib.c | 0 ...{from-boundary.luau => from_boundary.luau} | 0 ...{into-boundary.luau => into_boundary.luau} | 0 .../{pretty-print.luau => pretty_print.luau} | 0 19 files changed, 78 insertions(+), 107 deletions(-) delete mode 100644 tests/ffi/external-closure/lib.c rename tests/ffi/{external-closure => external_closure}/init.luau (52%) create mode 100644 tests/ffi/external_closure/lib.c rename tests/ffi/{external-math => external_math}/init.luau (96%) rename tests/ffi/{external-math => external_math}/lib.c (100%) rename tests/ffi/{external-pointer => external_pointer}/init.luau (53%) rename tests/ffi/{external-pointer => external_pointer}/lib.c (100%) rename tests/ffi/{external-print => external_print}/init.luau (89%) rename tests/ffi/{external-print => external_print}/lib.c (100%) rename tests/ffi/{external-struct => external_struct}/init.luau (94%) rename tests/ffi/{external-struct => external_struct}/lib.c (100%) rename tests/ffi/{from-boundary.luau => from_boundary.luau} (100%) rename tests/ffi/{into-boundary.luau => into_boundary.luau} (100%) rename tests/ffi/{pretty-print.luau => pretty_print.luau} (100%) diff --git a/crates/lune-std-ffi/README.md b/crates/lune-std-ffi/README.md index 0eca6a9..61ef8af 100644 --- a/crates/lune-std-ffi/README.md +++ b/crates/lune-std-ffi/README.md @@ -4,6 +4,25 @@ See [tests/ffi](../../tests/ffi/README.md) +## TODO + +- CString + +- Add buffer for owned data support + +- Add math operation. + + > `CTypeInfo:add(target, from1, from2, ...)` and `:sub` `:mul` `:div` `:mod` `:pow` + > Luau cannot handle f64, i64 or i128, so we should provide math operation for it + +- Add bit operation + + > Luau only supports 32bit bit operations + +- Add wchar and wstring support + + > For windows API + ## Code structure ### /c @@ -84,22 +103,3 @@ Implememt type-casting for all CTypes - **Const `FFI_STATUS_NAMES`:** Used for ffi_status stringify - **Function `get_ensured_size`:** Returns ensured ffi_type size - **Const `SIEE_OF_POINTER`:** Platform specific pointer size (Compile time known) - -## TODO - -- CString - -- Add buffer for owned data support - -- Add math operation. - - > `CTypeInfo:add(target, from1, from2, ...)` and `:sub` `:mul` `:div` `:mod` `:pow` - > Luau cannot handle f64, i64 or i128, so we should provide math operation for it - -- Add bit operation - - > Luau only supports 32bit bit operations - -- Add wchar and wstring support - - > For windows API diff --git a/crates/lune-std-ffi/src/c/fn_info.rs b/crates/lune-std-ffi/src/c/fn_info.rs index 3dd5444..ca78740 100644 --- a/crates/lune-std-ffi/src/c/fn_info.rs +++ b/crates/lune-std-ffi/src/c/fn_info.rs @@ -198,7 +198,7 @@ impl CFnInfo { } pub fn get_middle_type() -> Type { - Type::void() + Type::pointer() } } diff --git a/crates/lune-std-ffi/src/data/callable_data.rs b/crates/lune-std-ffi/src/data/callable_data.rs index 780f4e2..2421143 100644 --- a/crates/lune-std-ffi/src/data/callable_data.rs +++ b/crates/lune-std-ffi/src/data/callable_data.rs @@ -32,10 +32,7 @@ impl CallableData { } } - // TODO? async call: if have no lua closure in arguments, fficallble can be called with async way - pub unsafe fn call(&self, result: LuaValue, args: LuaMultiValue) -> LuaResult<()> { - // cache Vec => unable to create async call but no allocation let mut arg_list = Vec::<*mut c_void>::with_capacity(self.arg_info_list.len()); let result_pointer = if self.result_info.size == 0 { @@ -50,7 +47,6 @@ impl CallableData { .cast::(); for index in 0..self.arg_info_list.len() { - // let arg_info = self.arg_info_list.get(index).unwrap(); let arg_value = args .get(index) .ok_or_else(|| LuaError::external(format!("argument {index} required")))? @@ -59,14 +55,6 @@ impl CallableData { let arg_ref = arg_value.borrow::()?; - // unsafe { - // let argp = arg_ref.get_inner_pointer(); - // let fnr = transmute::<*mut c_void, unsafe extern "C" fn(i32, i32) -> i32>( - // *argp.cast::<*mut c_void>(), - // ); - // dbg!(fnr(1, 2)); - // } - arg_list.push(arg_ref.get_inner_pointer().cast::()); } diff --git a/crates/lune-std-ffi/src/data/closure_data.rs b/crates/lune-std-ffi/src/data/closure_data.rs index 17cc71f..bd4256f 100644 --- a/crates/lune-std-ffi/src/data/closure_data.rs +++ b/crates/lune-std-ffi/src/data/closure_data.rs @@ -1,5 +1,5 @@ use core::ffi::c_void; -use std::{borrow::Borrow, mem::transmute, ptr}; +use std::{borrow::Borrow, ptr}; use libffi::{ low::{closure_alloc, closure_free, ffi_cif}, @@ -20,7 +20,7 @@ use crate::ffi::{ pub struct ClosureData { lua: *const Lua, closure: *mut ffi_closure, - code: *mut c_void, + code: Box<*mut c_void>, arg_info_list: Vec, result_info: FfiResult, func: LuaRegistryKey, @@ -44,14 +44,11 @@ unsafe extern "C" fn callback( arg_pointers: *mut *mut c_void, closure_data: *mut c_void, ) { - dbg!("before ud"); let closure_data = closure_data.cast::().as_ref().unwrap(); let lua = closure_data.lua.as_ref().unwrap(); let len = (*cif).nargs as usize; let mut args = Vec::::with_capacity(len + 1); - dbg!("before result", closure_data.result_info.size); - // Push result pointer (ref) args.push(LuaValue::UserData( lua.create_userdata(RefData::new( @@ -62,8 +59,6 @@ unsafe extern "C" fn callback( .unwrap(), )); - dbg!("before arg"); - // Push arg pointer (ref) for i in 0..len { let arg_info = closure_data.arg_info_list.get(i).unwrap(); @@ -77,8 +72,6 @@ unsafe extern "C" fn callback( )); } - dbg!("before call"); - closure_data .func .borrow() @@ -101,51 +94,36 @@ impl ClosureData { let (closure, code) = closure_alloc(); let code = code.as_mut_ptr(); - dbg!(result_info.size); - let closure_data = lua.create_userdata(ClosureData { lua: ptr::from_ref(lua), closure, - code, + code: Box::new(code), arg_info_list, result_info, func, })?; - dbg!(unsafe { - closure_data - .to_pointer() - .cast::() - .as_ref() - .unwrap() - .result_info - .size - }); + let closure_data_ptr = ptr::from_ref(&*closure_data.borrow::()?); ffi_status_assert(unsafe { ffi_prep_closure_loc( closure, cif, Some(callback), - closure_data.to_pointer().cast_mut(), + closure_data_ptr.cast::().cast_mut(), code, ) })?; - unsafe { - // let argp = closure_data.borrow::()?.get_inner_pointer(); - let fnr = transmute::<*mut c_void, unsafe extern "C" fn(i32, i32) -> i32>(code); - dbg!(fnr(1, 2)); - } - Ok(closure_data) } } impl FfiData for ClosureData { unsafe fn get_inner_pointer(&self) -> *mut () { - ptr::from_ref(&self.code).cast_mut().cast::<()>() - // self.code.cast::<()>() + ptr::from_ref::<*mut c_void>(&*self.code) + .cast::<()>() + .cast_mut() } fn check_inner_boundary(&self, offset: isize, size: usize) -> bool { (offset as usize) + size <= SIZE_OF_POINTER @@ -166,15 +144,6 @@ impl LuaUserData for ClosureData { CLOSURE_REF_FLAGS, UNSIZED_BOUNDS, ))?; - unsafe { - let mut b = this.borrow_mut::()?; - b.lua = ptr::from_ref(lua); - let argp = b.get_inner_pointer(); - let fnr = transmute::<*mut c_void, unsafe extern "C" fn(i32, i32) -> i32>( - *argp.cast::<*mut c_void>(), - ); - dbg!(fnr(1, 2)); - } association::set(lua, CLSOURE_REF_INNER, &ref_data, &this)?; Ok(ref_data) }); diff --git a/tests/ffi/README.md b/tests/ffi/README.md index 5b33949..4d093cc 100644 --- a/tests/ffi/README.md +++ b/tests/ffi/README.md @@ -8,29 +8,29 @@ gcc for library compiling (for external-\*) **External tests** -- [x] tests/ffi/external-math -- [x] tests/ffi/external-pointer -- [x] tests/ffi/external-print -- [x] tests/ffi/external-struct -- [ ] tests/ffi/external-closure +- [x] [external_math](./external_math/init.luau) +- [x] [external_pointer](./external_pointer/init.luau) +- [x] [external_print](./external_print/init.luau) +- [x] [external_struct](./external_struct/init.luau) +- [ ] [external_closure](./external_closure/init.luau) > failed (segfault) **Luau-side** -- [ ] tests/ffi/pretty-print :white_check_mark: +- [ ] [pretty_print](./pretty_print) > need box, ref test -- [x] tests/ffi/isInteger -- [ ] tests/ffi/into-boundary +- [x] [isInteger](./isInteger) +- [ ] [into_boundary](./into_boundary) > need assertion -- [ ] tests/ffi/from-boundary +- [ ] [from_boundary](./from_boundary) > need assertion -- [ ] tests/ffi/cast +- [ ] [cast](./cast) > need assertion diff --git a/tests/ffi/external-closure/lib.c b/tests/ffi/external-closure/lib.c deleted file mode 100644 index 167a2f5..0000000 --- a/tests/ffi/external-closure/lib.c +++ /dev/null @@ -1,14 +0,0 @@ -#include - -typedef int (*lua_callback_t)(int, int); - -int closure_test(lua_callback_t callback) { - printf("%p\n", callback); - printf("%d\n", callback(12, 24)); - - return callback(12, 24) * 2; -} - -int closure(int a, int b) { - return a+b; -} diff --git a/tests/ffi/external-closure/init.luau b/tests/ffi/external_closure/init.luau similarity index 52% rename from tests/ffi/external-closure/init.luau rename to tests/ffi/external_closure/init.luau index a5783a7..4a3e4c7 100644 --- a/tests/ffi/external-closure/init.luau +++ b/tests/ffi/external_closure/init.luau @@ -1,6 +1,6 @@ local ffi = require("@lune/ffi") -local testdir = "./tests/ffi/external-closure" +local testdir = "./tests/ffi/external_closure" local compile = require("../utility/compile") compile(`{testdir}/lib.c`, `{testdir}/lib.so`) @@ -15,11 +15,27 @@ local function test_closure() local closure_test_info = ffi.c.fn({ callback_info }, ffi.c.int) - local closure_test_callable = closure_test_info:callable(lib:find("closure_test")) + local closure_test_callable = closure_test_info:callable(lib:find("closure")) local result_box = ffi.box(ffi.c.int.size) closure_test_callable(result_box, callback_closure:ref()) - print(callback_closure) + local result = ffi.c.int:readData(result_box) + assert(result == 72, `test_closure failed. result expected 20000, got {result}`) end test_closure() + +local function test_hello_world() + local callback_info = ffi.c.fn({}, ffi.c.void) + local callback_closure = callback_info:closure(function() + print("Hello world in lua closure!") + end) + + local closure_test_info = ffi.c.fn({ callback_info }, ffi.c.void) + + local closure_test_callable = closure_test_info:callable(lib:find("hello_world")) + + closure_test_callable(nil, callback_closure:ref()) +end + +test_hello_world() diff --git a/tests/ffi/external_closure/lib.c b/tests/ffi/external_closure/lib.c new file mode 100644 index 0000000..f14f100 --- /dev/null +++ b/tests/ffi/external_closure/lib.c @@ -0,0 +1,12 @@ +#include + +typedef int (*lua_callback_t)(int, int); +typedef void (*lua_hello_world_callback_t)(); + +int closure(lua_callback_t lua_closure) { + return lua_closure(12, 24) * 2; +} + +void hello_world(lua_hello_world_callback_t lua_closure) { + lua_closure(); +} diff --git a/tests/ffi/external-math/init.luau b/tests/ffi/external_math/init.luau similarity index 96% rename from tests/ffi/external-math/init.luau rename to tests/ffi/external_math/init.luau index 1cfd623..fe486b9 100644 --- a/tests/ffi/external-math/init.luau +++ b/tests/ffi/external_math/init.luau @@ -1,7 +1,7 @@ local ffi = require("@lune/ffi") local c = ffi.c -local testdir = "./tests/ffi/external-math" +local testdir = "./tests/ffi/external_math" local compile = require("../utility/compile") compile(`{testdir}/lib.c`, `{testdir}/lib.so`) local lib = ffi.open(`{testdir}/lib.so`) diff --git a/tests/ffi/external-math/lib.c b/tests/ffi/external_math/lib.c similarity index 100% rename from tests/ffi/external-math/lib.c rename to tests/ffi/external_math/lib.c diff --git a/tests/ffi/external-pointer/init.luau b/tests/ffi/external_pointer/init.luau similarity index 53% rename from tests/ffi/external-pointer/init.luau rename to tests/ffi/external_pointer/init.luau index 57fc719..a78f767 100644 --- a/tests/ffi/external-pointer/init.luau +++ b/tests/ffi/external_pointer/init.luau @@ -1,23 +1,23 @@ local ffi = require("@lune/ffi") local c = ffi.c -local testdir = "./tests/ffi/external-pointer" +local testdir = "./tests/ffi/external_pointer" local compile = require("../utility/compile") compile(`{testdir}/lib.c`, `{testdir}/lib.so`) local lib = ffi.open(`{testdir}/lib.so`) -local function test_pointer() - local pointer_info = c.fn({ c.int:ptr() }, c.void) +local function test_pointer_write() + local pointer_write_info = c.fn({ c.int:ptr() }, c.void) - local pointer_callable = pointer_info:callable(lib:find("pointer")) + local pointer_write_callable = pointer_write_info:callable(lib:find("pointer_write")) local a = ffi.box(c.int.size) - pointer_callable(nil, a:ref():ref()) + pointer_write_callable(nil, a:ref():ref()) local result = c.int:readData(a) assert(result == 123, `pointer failed. result expected 123, got {result}`) end -test_pointer() +test_pointer_write() diff --git a/tests/ffi/external-pointer/lib.c b/tests/ffi/external_pointer/lib.c similarity index 100% rename from tests/ffi/external-pointer/lib.c rename to tests/ffi/external_pointer/lib.c diff --git a/tests/ffi/external-print/init.luau b/tests/ffi/external_print/init.luau similarity index 89% rename from tests/ffi/external-print/init.luau rename to tests/ffi/external_print/init.luau index 341481b..174fdc2 100644 --- a/tests/ffi/external-print/init.luau +++ b/tests/ffi/external_print/init.luau @@ -1,7 +1,7 @@ local ffi = require("@lune/ffi") local c = ffi.c -local testdir = "./tests/ffi/external-print" +local testdir = "./tests/ffi/external_print" local compile = require("../utility/compile") compile(`{testdir}/lib.c`, `{testdir}/lib.so`) local lib = ffi.open(`{testdir}/lib.so`) diff --git a/tests/ffi/external-print/lib.c b/tests/ffi/external_print/lib.c similarity index 100% rename from tests/ffi/external-print/lib.c rename to tests/ffi/external_print/lib.c diff --git a/tests/ffi/external-struct/init.luau b/tests/ffi/external_struct/init.luau similarity index 94% rename from tests/ffi/external-struct/init.luau rename to tests/ffi/external_struct/init.luau index 0b3c829..d3ae98a 100644 --- a/tests/ffi/external-struct/init.luau +++ b/tests/ffi/external_struct/init.luau @@ -1,7 +1,7 @@ local ffi = require("@lune/ffi") local c = ffi.c -local testdir = "./tests/ffi/external-struct" +local testdir = "./tests/ffi/external_struct" local compile = require("../utility/compile") compile(`{testdir}/lib.c`, `{testdir}/lib.so`) local lib = ffi.open(`{testdir}/lib.so`) diff --git a/tests/ffi/external-struct/lib.c b/tests/ffi/external_struct/lib.c similarity index 100% rename from tests/ffi/external-struct/lib.c rename to tests/ffi/external_struct/lib.c diff --git a/tests/ffi/from-boundary.luau b/tests/ffi/from_boundary.luau similarity index 100% rename from tests/ffi/from-boundary.luau rename to tests/ffi/from_boundary.luau diff --git a/tests/ffi/into-boundary.luau b/tests/ffi/into_boundary.luau similarity index 100% rename from tests/ffi/into-boundary.luau rename to tests/ffi/into_boundary.luau diff --git a/tests/ffi/pretty-print.luau b/tests/ffi/pretty_print.luau similarity index 100% rename from tests/ffi/pretty-print.luau rename to tests/ffi/pretty_print.luau