-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
335 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
use core::ffi::c_void; | ||
use std::cell::Ref; | ||
// use std::ptr; | ||
|
||
use libffi::{ | ||
// low::{closure_alloc, ffi_cif, CodePtr, RawCallback}, | ||
low::{ffi_cif, CodePtr}, | ||
// middle::Cif, | ||
// raw::ffi_prep_closure_loc, | ||
}; | ||
use mlua::prelude::*; | ||
|
||
use super::{ | ||
bit_mask::u8_test_not, ffi_native::NativeArgInfo, FfiRef, FfiRefFlag, GetNativeData, | ||
NativeConvert, NativeData, | ||
}; | ||
|
||
// unsafe extern "C" fn callback() { | ||
// _cif: ffi_cif, | ||
// result: &mut | ||
// } | ||
|
||
// pub type RawCallback = unsafe extern "C" fn(cif: *mut ffi_cif, result: *mut c_void, args: *mut *mut c_void, userdata: *mut c_void); | ||
// pub unsafe extern "C" fn ffi_prep_raw_closure( | ||
// arg1: *mut ffi_raw_closure, | ||
// cif: *mut ffi_cif, | ||
// fun: Option<unsafe extern "C" fn(_: *mut ffi_cif, _: *mut c_void, _: *mut ffi_raw, _: *mut c_void)>, | ||
// user_data: *mut c_void | ||
// ) -> u32 | ||
|
||
// pub fn ffi_prep_raw_closure_loc( | ||
// arg1: *mut ffi_raw_closure, | ||
// cif: *mut ffi_cif, | ||
// fun: Option< | ||
// unsafe extern "C" fn( | ||
// arg1: *mut ffi_cif, | ||
// arg2: *mut c_void, | ||
// arg3: *mut ffi_raw, | ||
// arg4: *mut c_void, | ||
// ), | ||
// >, | ||
// user_data: *mut c_void, | ||
// codeloc: *mut c_void, | ||
// ) -> ffi_status; | ||
|
||
pub struct FfiCallable { | ||
cif: *mut ffi_cif, | ||
arg_type_list: Vec<NativeArgInfo>, | ||
result_size: usize, | ||
code: CodePtr, | ||
} | ||
|
||
impl FfiCallable { | ||
pub unsafe fn new( | ||
cif: *mut ffi_cif, | ||
arg_type_list: Vec<NativeArgInfo>, | ||
result_size: usize, | ||
function_ref: FfiRef, | ||
) -> LuaResult<Self> { | ||
if u8_test_not(function_ref.flags, FfiRefFlag::Function.value()) { | ||
return Err(LuaError::external("ref is not function pointer")); | ||
} | ||
Ok(Self { | ||
cif, | ||
arg_type_list, | ||
result_size, | ||
code: CodePtr::from_ptr(function_ref.get_pointer(0).cast::<c_void>()), | ||
}) | ||
} | ||
|
||
pub unsafe fn call(&self, result: &Ref<dyn NativeData>, args: LuaMultiValue) -> LuaResult<()> { | ||
result | ||
.check_boundary(0, self.result_size) | ||
.then_some(()) | ||
.ok_or_else(|| LuaError::external("result boundary check failed")) | ||
} | ||
// pub fn new_from_lua_table(lua: &Lua, args: LuaTable, ret: LuaAnyUserData) -> LuaResult<Self> { | ||
// let args_types = libffi_type_list_from_table(lua, &args)?; | ||
// let ret_type = libffi_type_from_userdata(lua, &ret)?; | ||
|
||
// Ok(Self::new( | ||
// args_types, | ||
// ret_type, | ||
// unsafe { get_conv_list_from_table(&args)? }, | ||
// unsafe { get_conv(&ret)? }, | ||
// )) | ||
// } | ||
// pub fn call() { | ||
|
||
// } | ||
} | ||
|
||
impl LuaUserData for FfiCallable { | ||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { | ||
methods.add_method( | ||
"call", | ||
|_lua, this: &FfiCallable, mut args: LuaMultiValue| { | ||
let LuaValue::UserData(result) = args.pop_front().ok_or_else(|| { | ||
LuaError::external("first argument must be result data handle") | ||
})? | ||
else { | ||
return Err(LuaError::external("")); | ||
}; | ||
let call_result = unsafe { this.call(&result.get_data_handle()?, args) }; | ||
call_result | ||
}, | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
use core::ffi::c_void; | ||
use std::ptr; | ||
|
||
use libffi::{ | ||
low::{closure_alloc, closure_free, ffi_cif, CodePtr}, | ||
raw::{ffi_closure, ffi_prep_closure_loc}, | ||
}; | ||
use mlua::prelude::*; | ||
|
||
use super::{ | ||
ffi_ref::{FfiRefBounds, FfiRefFlag}, | ||
FfiRef, FFI_STATUS_NAMES, | ||
}; | ||
|
||
pub struct FfiClosure<'a> { | ||
closure: *mut ffi_closure, | ||
code: CodePtr, | ||
userdata: CallbackUserdata<'a>, | ||
} | ||
|
||
impl<'a> Drop for FfiClosure<'a> { | ||
fn drop(&mut self) { | ||
unsafe { | ||
closure_free(self.closure); | ||
} | ||
} | ||
} | ||
|
||
#[allow(unused)] | ||
pub struct CallbackUserdata<'a> { | ||
pub func: LuaFunction<'a>, | ||
pub lua: &'a Lua, | ||
pub arg_ref_flags: Vec<u8>, | ||
pub arg_ref_size: Vec<usize>, | ||
pub result_size: usize, | ||
} | ||
|
||
const RESULT_REF_FLAGS: u8 = FfiRefFlag::Leaked.value() | FfiRefFlag::Writable.value(); | ||
|
||
unsafe extern "C" fn callback( | ||
cif: *mut ffi_cif, | ||
result_pointer: *mut c_void, | ||
arg_pointers: *mut *mut c_void, | ||
userdata: *mut c_void, | ||
) { | ||
let userdata = userdata.cast::<CallbackUserdata>(); | ||
let len = (*cif).nargs as usize; | ||
let mut args = Vec::<LuaValue>::with_capacity(len + 1); | ||
|
||
// Push result pointer (ref) | ||
args.push(LuaValue::UserData( | ||
(*userdata) | ||
.lua | ||
.create_userdata(FfiRef::new( | ||
result_pointer.cast::<()>(), | ||
RESULT_REF_FLAGS, | ||
FfiRefBounds::new(0, (*userdata).result_size), | ||
)) | ||
.unwrap(), | ||
)); | ||
|
||
// Push arg pointer (ref) | ||
for i in 0..len { | ||
args.push(LuaValue::UserData( | ||
(*userdata) | ||
.lua | ||
.create_userdata(FfiRef::new( | ||
(*arg_pointers.add(i)).cast::<()>(), | ||
(*userdata).arg_ref_flags.get(i).unwrap().to_owned(), | ||
FfiRefBounds::new(0, (*userdata).arg_ref_size.get(i).unwrap().to_owned()), | ||
)) | ||
.unwrap(), | ||
)); | ||
} | ||
|
||
(*userdata).func.call::<_, ()>(args).unwrap(); | ||
} | ||
|
||
impl<'a> FfiClosure<'a> { | ||
pub unsafe fn new( | ||
cif: *mut ffi_cif, | ||
userdata: CallbackUserdata<'a>, | ||
) -> LuaResult<FfiClosure<'a>> { | ||
let (closure, code) = closure_alloc(); | ||
let prep_result = ffi_prep_closure_loc( | ||
closure, | ||
cif, | ||
Some(callback), | ||
ptr::from_ref(&userdata).cast::<c_void>().cast_mut(), | ||
code.as_mut_ptr(), | ||
); | ||
|
||
if prep_result != 0 { | ||
Err(LuaError::external(format!( | ||
"ffi_get_struct_offsets failed. expected result {}, got {}", | ||
FFI_STATUS_NAMES[0], FFI_STATUS_NAMES[prep_result as usize] | ||
))) | ||
} else { | ||
Ok(FfiClosure { | ||
closure, | ||
code, | ||
userdata, | ||
}) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
use super::NativeConvert; | ||
|
||
pub struct FfiArgRefOption { | ||
pub flag: u8, | ||
} | ||
|
||
pub enum NativeArgType { | ||
FfiBox, | ||
FfiRef(FfiArgRefOption), | ||
} | ||
|
||
pub struct NativeArgInfo { | ||
pub conv: *const dyn NativeConvert, | ||
pub kind: NativeArgType, | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.