mirror of
https://github.com/lune-org/lune.git
synced 2025-04-10 21:40:54 +01:00
Export ctypes and implement signedness (#243)
This commit is contained in:
parent
48d2db4950
commit
3ccb0720fd
39 changed files with 1359 additions and 735 deletions
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
@ -23,9 +23,5 @@
|
||||||
},
|
},
|
||||||
"[rust]": {
|
"[rust]": {
|
||||||
"editor.defaultFormatter": "rust-lang.rust-analyzer"
|
"editor.defaultFormatter": "rust-lang.rust-analyzer"
|
||||||
},
|
|
||||||
"files.associations": {
|
|
||||||
"*.inc": "c",
|
|
||||||
"random": "c"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
TODO: rewrite docs
|
|
||||||
|
|
||||||
# Raw
|
|
||||||
|
|
||||||
Data received from external. You can move this data into a box, use it as a ref, or change it directly to a Lua value.
|
|
||||||
The raw data is not on Lua's heap.
|
|
||||||
|
|
||||||
Raw:toRef()
|
|
||||||
Convert data into ref. it allocate new lua userdata
|
|
||||||
|
|
||||||
Raw:toBox()
|
|
||||||
Convert data into box. it allocate new lua userdata
|
|
||||||
|
|
||||||
Raw:intoBox()
|
|
||||||
Raw:intoRef()
|
|
||||||
|
|
||||||
See type:fromRaw()
|
|
||||||
|
|
||||||
# Box
|
|
||||||
|
|
||||||
`ffi.box(size)`
|
|
||||||
|
|
||||||
Create new userdata with sized by `size` argument. Box is untyped, and have no ABI information. You can write some data into box with `type`
|
|
||||||
|
|
||||||
All operation with box will boundary checked. GC will free heap well.
|
|
||||||
|
|
||||||
일반적으로 포인터를 넘겨주기 위해서 사용됩니다. 박스의 공간은 ref 할 수 있으며. 함수를 수행한 후 루아에서 읽어볼 수 있습니다.
|
|
||||||
|
|
||||||
## :zero()
|
|
||||||
박스를 0 으로 채워넣습니다. 기본적으로 박스는 초기화될 때 0 으로 채워지기 때문에 박스를 다시 0 으로 초기화하고 싶을 경우에 사용하십시오.
|
|
||||||
|
|
||||||
## :copy(targetbox,size,offset?=0,targetoffset?=0)
|
|
||||||
박스 안의 값을 다른 박스에 복사합니다. 바운더리가 확인되어지므로 안전합니다.
|
|
||||||
|
|
||||||
## .size
|
|
||||||
이 박스의 크기입니다.
|
|
||||||
|
|
||||||
## :ref(offset?=0) => ref
|
|
||||||
이 박스를 참조합니다. 참조가 살아있는 동안 박스는 수거되지 않습니다. 일반적으로 외부의 함수에 포인터를 넘겨주기 위해서 사용됩니다.
|
|
||||||
|
|
||||||
## more stuffs (not planned at this time)
|
|
||||||
|
|
||||||
ref=>buffer conversion, or bit/byte related?
|
|
||||||
|
|
||||||
# Ref (Unsafe)
|
|
||||||
|
|
||||||
바운더리를 처리하지 않는 포인터입니다. 외부에서 받은 포인터, 또는 박스로부터 만들어진 포인터입니다.
|
|
||||||
ref 는 바운더리를 검사하지 않으므로 안전하지 않습니다.
|
|
||||||
|
|
||||||
## :offset(bytes)
|
|
||||||
|
|
||||||
이 ref 와 상대적인 위치에 있는 ref 를 구합니다.
|
|
||||||
|
|
||||||
## :writefromRef()
|
|
||||||
다른 ref 안의 값을 읽어와 이 ref 안에 씁니다. 아래와 비슷한 연산을 합니다
|
|
||||||
```c
|
|
||||||
int a = 100,b;
|
|
||||||
```
|
|
||||||
|
|
||||||
## :writefromBox()
|
|
||||||
box 값을 읽어와서 쓰기
|
|
||||||
|
|
||||||
# Type
|
|
||||||
|
|
||||||
`type` is abstract class that helps encoding data into `box` or decode data from `box`
|
|
||||||
|
|
||||||
## :toBox(luavalue)
|
|
||||||
Convert lua value to box. box will sized with `type.size`
|
|
||||||
|
|
||||||
## :fromBox(box,offset?=0)
|
|
||||||
Read data from box, and convert into lua value.
|
|
||||||
Boundary will checked
|
|
||||||
|
|
||||||
## :intoBox(luavalue,box,offset?=0)
|
|
||||||
Convert lua value, and write into box
|
|
||||||
Boundary will checked
|
|
||||||
|
|
||||||
## :fromRef(ref,offset?=0)
|
|
||||||
포인터가 가르키는 곳의 데이터를 읽어서 루아의 데이터로 변환합니다.
|
|
||||||
|
|
||||||
## :intoRef(luavalue,ref,offset?=0)
|
|
||||||
포인터가 가르키는 곳에 데이터를 작성합니다.
|
|
||||||
|
|
||||||
## :fromRaw(raw,offset?=0)
|
|
||||||
|
|
||||||
|
|
||||||
## :ptr() -> Ptr
|
|
||||||
Get pointer type
|
|
||||||
|
|
||||||
## :arr(len) -> Arr
|
|
||||||
Get array type
|
|
||||||
|
|
||||||
## .size
|
|
||||||
|
|
||||||
Byte size of this type. you can initialize box with
|
|
||||||
|
|
||||||
## :cast(box,type) TODO
|
|
||||||
|
|
||||||
# Ptr
|
|
||||||
Pointer type of some type.
|
|
||||||
|
|
||||||
Ptr is not data converter. It only works for type hint of `struct` or `fn`
|
|
||||||
|
|
||||||
## .inner
|
|
||||||
Inner type
|
|
||||||
|
|
||||||
## .size
|
|
||||||
Size of `usize`
|
|
||||||
|
|
||||||
:ptr()
|
|
||||||
:arr()
|
|
||||||
|
|
||||||
## Arr
|
|
||||||
|
|
||||||
## Void
|
|
||||||
|
|
||||||
`ffi.void`
|
|
||||||
|
|
||||||
Zero sized type.
|
|
||||||
|
|
||||||
## Fn
|
|
||||||
Prototype type of some function. converts lua function into native function pointer or native function pointer into lua function.
|
|
||||||
|
|
||||||
`ffi.fn({ type }, type) -> fn`
|
|
||||||
|
|
||||||
:toLua( ref ) -> luafunction
|
|
||||||
:toBox( luafunction ) -> ref
|
|
||||||
|
|
||||||
> TODO: rust, and another ABI support
|
|
|
@ -113,16 +113,6 @@ impl CStruct {
|
||||||
impl LuaUserData for CStruct {
|
impl LuaUserData for CStruct {
|
||||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
fields.add_field_method_get("size", |_, this| Ok(this.size));
|
fields.add_field_method_get("size", |_, this| Ok(this.size));
|
||||||
|
|
||||||
// Simply pass in the locked table used when first creating this object.
|
|
||||||
// By strongly referencing the table, the types inside do not disappear
|
|
||||||
// and the user can read the contents as needed. (good recycling!)
|
|
||||||
fields.add_field_function_get("inner", |lua, this: LuaAnyUserData| {
|
|
||||||
let table: LuaValue = get_association(lua, CSTRUCT_INNER, this)?
|
|
||||||
// It shouldn't happen.
|
|
||||||
.ok_or(LuaError::external("inner field not found"))?;
|
|
||||||
Ok(table)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
@ -130,6 +120,18 @@ impl LuaUserData for CStruct {
|
||||||
let offset = this.offset(index)?;
|
let offset = this.offset(index)?;
|
||||||
Ok(offset)
|
Ok(offset)
|
||||||
});
|
});
|
||||||
|
// Simply pass type in the locked table used when first creating this object.
|
||||||
|
// By referencing the table to struct, the types inside do not disappear
|
||||||
|
methods.add_function("field", |lua, (this, field): (LuaAnyUserData, usize)| {
|
||||||
|
if let LuaValue::Table(t) = get_association(lua, CSTRUCT_INNER, this)?
|
||||||
|
.ok_or(LuaError::external("Field table not found"))?
|
||||||
|
{
|
||||||
|
let value: LuaValue = t.get(field + 1)?;
|
||||||
|
Ok(value)
|
||||||
|
} else {
|
||||||
|
Err(LuaError::external("Failed to read field table"))
|
||||||
|
}
|
||||||
|
});
|
||||||
methods.add_function("ptr", |lua, this: LuaAnyUserData| {
|
methods.add_function("ptr", |lua, this: LuaAnyUserData| {
|
||||||
let pointer = CPtr::from_lua_userdata(lua, &this)?;
|
let pointer = CPtr::from_lua_userdata(lua, &this)?;
|
||||||
Ok(pointer)
|
Ok(pointer)
|
||||||
|
|
|
@ -1,28 +1,19 @@
|
||||||
#![allow(clippy::cargo_common_metadata)]
|
#![allow(clippy::cargo_common_metadata)]
|
||||||
|
|
||||||
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
|
|
||||||
use num::cast::AsPrimitive;
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use libffi::middle::Type;
|
use libffi::middle::Type;
|
||||||
|
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
use super::association_names::CTYPE_STATIC;
|
use super::{
|
||||||
use super::c_arr::CArr;
|
association_names::CTYPE_STATIC, c_arr::CArr, c_helper::get_ensured_size, c_ptr::CPtr,
|
||||||
use super::c_helper::get_ensured_size;
|
};
|
||||||
use super::c_ptr::CPtr;
|
use crate::ffi::{
|
||||||
use crate::ffi::ffi_association::set_association;
|
ffi_association::set_association,
|
||||||
use crate::ffi::ffi_helper::get_ptr_from_userdata;
|
ffi_native::{NativeCast, NativeConvert},
|
||||||
|
};
|
||||||
pub struct CType<T: ?Sized> {
|
|
||||||
// for ffi_ptrarray_to_raw?
|
|
||||||
// libffi_cif: Cif,
|
|
||||||
libffi_type: Type,
|
|
||||||
size: usize,
|
|
||||||
name: Option<&'static str>,
|
|
||||||
signedness: bool,
|
|
||||||
_phantom: PhantomData<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// We can't get a CType<T> through mlua, something like
|
// We can't get a CType<T> through mlua, something like
|
||||||
// .is::<CType<dyn Any>> will fail.
|
// .is::<CType<dyn Any>> will fail.
|
||||||
|
@ -35,28 +26,34 @@ pub struct CTypeStatic {
|
||||||
pub name: Option<&'static str>,
|
pub name: Option<&'static str>,
|
||||||
pub signedness: bool,
|
pub signedness: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CTypeStatic {
|
impl CTypeStatic {
|
||||||
fn new<T>(ctype: &CType<T>) -> Self {
|
fn new<T>(ctype: &CType<T>, signedness: bool) -> Self {
|
||||||
Self {
|
Self {
|
||||||
libffi_type: ctype.libffi_type.clone(),
|
libffi_type: ctype.libffi_type.clone(),
|
||||||
size: ctype.size,
|
size: ctype.size,
|
||||||
name: ctype.name,
|
name: ctype.name,
|
||||||
signedness: ctype.signedness,
|
signedness,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl LuaUserData for CTypeStatic {}
|
impl LuaUserData for CTypeStatic {}
|
||||||
|
|
||||||
|
pub struct CType<T: ?Sized> {
|
||||||
|
// for ffi_ptrarray_to_raw?
|
||||||
|
// libffi_cif: Cif,
|
||||||
|
libffi_type: Type,
|
||||||
|
size: usize,
|
||||||
|
name: Option<&'static str>,
|
||||||
|
_phantom: PhantomData<T>,
|
||||||
|
}
|
||||||
impl<T> CType<T>
|
impl<T> CType<T>
|
||||||
where
|
where
|
||||||
T: 'static,
|
T: 'static,
|
||||||
Self: CTypeConvert + CTypeCast,
|
Self: NativeConvert + CTypeCast + CTypeSignedness,
|
||||||
{
|
{
|
||||||
pub fn new_with_libffi_type<'lua>(
|
pub fn new_with_libffi_type<'lua>(
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
libffi_type: Type,
|
libffi_type: Type,
|
||||||
signedness: bool,
|
|
||||||
name: Option<&'static str>,
|
name: Option<&'static str>,
|
||||||
) -> LuaResult<LuaAnyUserData<'lua>> {
|
) -> LuaResult<LuaAnyUserData<'lua>> {
|
||||||
// let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void());
|
// let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void());
|
||||||
|
@ -67,10 +64,10 @@ where
|
||||||
libffi_type,
|
libffi_type,
|
||||||
size,
|
size,
|
||||||
name,
|
name,
|
||||||
signedness,
|
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
};
|
};
|
||||||
let userdata_static = lua.create_any_userdata(CTypeStatic::new::<T>(&ctype))?;
|
let userdata_static =
|
||||||
|
lua.create_any_userdata(CTypeStatic::new::<T>(&ctype, ctype.get_signedness()))?;
|
||||||
let userdata = lua.create_userdata(ctype)?;
|
let userdata = lua.create_userdata(ctype)?;
|
||||||
|
|
||||||
set_association(lua, CTYPE_STATIC, &userdata, &userdata_static)?;
|
set_association(lua, CTYPE_STATIC, &userdata, &userdata_static)?;
|
||||||
|
@ -85,57 +82,13 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<T> NativeCast for CType<T> {}
|
||||||
|
|
||||||
// Handle C data, provide type conversion between luavalue and c-type
|
// Cast native data
|
||||||
pub trait CTypeConvert {
|
pub trait CTypeCast
|
||||||
// Convert luavalue into data, then write into ptr
|
where
|
||||||
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()>;
|
Self: NativeCast,
|
||||||
|
{
|
||||||
// Read data from ptr, then convert into luavalue
|
|
||||||
fn ptr_into_luavalue(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue>;
|
|
||||||
|
|
||||||
// Read data from userdata (such as box or ref) and convert it into luavalue
|
|
||||||
unsafe fn read_userdata<'lua>(
|
|
||||||
&self,
|
|
||||||
lua: &'lua Lua,
|
|
||||||
userdata: LuaAnyUserData<'lua>,
|
|
||||||
offset: Option<isize>,
|
|
||||||
) -> LuaResult<LuaValue<'lua>> {
|
|
||||||
let ptr = unsafe { get_ptr_from_userdata(&userdata, offset)? };
|
|
||||||
let value = Self::ptr_into_luavalue(lua, ptr)?;
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write data into userdata (such as box or ref) from luavalue
|
|
||||||
unsafe fn write_userdata<'lua>(
|
|
||||||
&self,
|
|
||||||
luavalue: LuaValue<'lua>,
|
|
||||||
userdata: LuaAnyUserData<'lua>,
|
|
||||||
offset: Option<isize>,
|
|
||||||
) -> LuaResult<()> {
|
|
||||||
let ptr = unsafe { get_ptr_from_userdata(&userdata, offset)? };
|
|
||||||
Self::luavalue_into_ptr(luavalue, ptr)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait CTypeCast {
|
|
||||||
// Cast T as U
|
|
||||||
fn cast_num<T, U>(&self, from: &LuaAnyUserData, into: &LuaAnyUserData) -> LuaResult<()>
|
|
||||||
where
|
|
||||||
T: AsPrimitive<U>,
|
|
||||||
U: 'static + Copy,
|
|
||||||
{
|
|
||||||
let from_ptr = unsafe { get_ptr_from_userdata(from, None)?.cast::<T>() };
|
|
||||||
let into_ptr = unsafe { get_ptr_from_userdata(into, None)?.cast::<U>() };
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
*into_ptr = (*from_ptr).as_();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_cast_num<T, U>(
|
fn try_cast_num<T, U>(
|
||||||
&self,
|
&self,
|
||||||
ctype: &LuaAnyUserData,
|
ctype: &LuaAnyUserData,
|
||||||
|
@ -154,7 +107,6 @@ pub trait CTypeCast {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
fn cast(
|
fn cast(
|
||||||
&self,
|
&self,
|
||||||
from_ctype: &LuaAnyUserData,
|
from_ctype: &LuaAnyUserData,
|
||||||
|
@ -179,31 +131,52 @@ pub trait CTypeCast {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait CTypeSignedness {
|
||||||
|
fn get_signedness(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> LuaUserData for CType<T>
|
impl<T> LuaUserData for CType<T>
|
||||||
where
|
where
|
||||||
T: 'static,
|
T: 'static,
|
||||||
Self: CTypeConvert + CTypeCast,
|
Self: CTypeCast + CTypeSignedness + NativeCast + NativeConvert,
|
||||||
{
|
{
|
||||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
fields.add_field_method_get("size", |_, this| Ok(this.size));
|
fields.add_field_method_get("size", |_, this| Ok(this.size));
|
||||||
fields.add_meta_field(LuaMetaMethod::Type, "CType");
|
fields.add_meta_field(LuaMetaMethod::Type, "CType");
|
||||||
fields.add_field_method_get("signedness", |_, this| Ok(this.signedness));
|
fields.add_field_method_get("signedness", |_, this| Ok(this.get_signedness()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
methods.add_function("ptr", |lua, this: LuaAnyUserData| {
|
methods.add_function("ptr", |lua, this: LuaAnyUserData| {
|
||||||
CPtr::from_lua_userdata(lua, &this)
|
CPtr::from_lua_userdata(lua, &this)
|
||||||
});
|
});
|
||||||
methods.add_method(
|
methods.add_function(
|
||||||
"from",
|
"from",
|
||||||
|lua, ctype, (userdata, offset): (LuaAnyUserData, Option<isize>)| unsafe {
|
|lua,
|
||||||
ctype.read_userdata(lua, userdata, offset)
|
(ctype, userdata, offset): (
|
||||||
|
LuaAnyUserData,
|
||||||
|
LuaAnyUserData,
|
||||||
|
Option<isize>,
|
||||||
|
)| unsafe {
|
||||||
|
ctype
|
||||||
|
.borrow::<CType<T>>()?
|
||||||
|
.read_userdata(&ctype, lua, &userdata, offset)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
methods.add_method(
|
methods.add_function(
|
||||||
"into",
|
"into",
|
||||||
|_, ctype, (value, userdata, offset): (LuaValue, LuaAnyUserData, Option<isize>)| unsafe {
|
|lua,
|
||||||
ctype.write_userdata(value, userdata, offset)
|
(ctype, value, userdata, offset): (
|
||||||
|
LuaAnyUserData,
|
||||||
|
LuaValue,
|
||||||
|
LuaAnyUserData,
|
||||||
|
Option<isize>,
|
||||||
|
)| unsafe {
|
||||||
|
ctype
|
||||||
|
.borrow::<CType<T>>()?
|
||||||
|
.write_userdata(&ctype, lua, value, userdata, offset)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| {
|
methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| {
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
pub(super) mod c_arr;
|
pub use types::create_all_c_types;
|
||||||
pub(super) mod c_fn;
|
|
||||||
pub(super) mod c_helper;
|
|
||||||
pub(super) mod c_ptr;
|
|
||||||
pub(super) mod c_string;
|
|
||||||
pub(super) mod c_struct;
|
|
||||||
pub(super) mod c_type;
|
|
||||||
pub(super) mod types;
|
|
||||||
|
|
||||||
pub use types::create_all_types;
|
pub use types::create_all_types;
|
||||||
|
|
||||||
|
pub mod c_arr;
|
||||||
|
pub mod c_fn;
|
||||||
|
pub mod c_helper;
|
||||||
|
pub mod c_ptr;
|
||||||
|
pub mod c_string;
|
||||||
|
pub mod c_struct;
|
||||||
|
pub mod c_type;
|
||||||
|
pub mod types;
|
||||||
|
|
||||||
// Named registry table names
|
// Named registry table names
|
||||||
mod association_names {
|
mod association_names {
|
||||||
pub const CPTR_INNER: &str = "__cptr_inner";
|
pub const CPTR_INNER: &str = "__cptr_inner";
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
use core::ffi::*;
|
|
||||||
|
|
||||||
use libffi::middle::Type;
|
|
||||||
use mlua::prelude::*;
|
|
||||||
use num::cast::AsPrimitive;
|
|
||||||
|
|
||||||
use super::super::c_type::{CType, CTypeCast, CTypeConvert};
|
|
||||||
use crate::ffi::ffi_platform::CHAR_IS_SIGNED;
|
|
||||||
|
|
||||||
impl CTypeConvert for CType<c_char> {
|
|
||||||
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()> {
|
|
||||||
let value: c_char = match value {
|
|
||||||
LuaValue::Integer(t) => t.as_(),
|
|
||||||
LuaValue::String(t) => t.as_bytes().first().map_or(0, u8::to_owned).as_(),
|
|
||||||
_ => {
|
|
||||||
return Err(LuaError::external(format!(
|
|
||||||
"Argument LuaValue expected a Integer or String, got {}",
|
|
||||||
value.type_name()
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
unsafe {
|
|
||||||
*(ptr.cast::<c_char>()) = value;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn ptr_into_luavalue(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue> {
|
|
||||||
let value = unsafe { (*ptr.cast::<c_char>()).into_lua(lua)? };
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CTypeCast for CType<c_char> {
|
|
||||||
fn cast(
|
|
||||||
&self,
|
|
||||||
from_ctype: &LuaAnyUserData,
|
|
||||||
into_ctype: &LuaAnyUserData,
|
|
||||||
from: &LuaAnyUserData,
|
|
||||||
into: &LuaAnyUserData,
|
|
||||||
) -> LuaResult<()> {
|
|
||||||
self.try_cast_num::<c_char, c_float>(into_ctype, from, into)?
|
|
||||||
.or(self.try_cast_num::<c_char, c_double>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_char, c_char>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_char, c_long>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_char, c_int>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_char, c_longlong>(into_ctype, from, into)?)
|
|
||||||
.ok_or_else(|| self.cast_failed_with(from_ctype, into_ctype))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
|
||||||
Ok((
|
|
||||||
"char",
|
|
||||||
CType::<c_char>::new_with_libffi_type(
|
|
||||||
lua,
|
|
||||||
if CHAR_IS_SIGNED {
|
|
||||||
Type::c_schar()
|
|
||||||
} else {
|
|
||||||
Type::c_uchar()
|
|
||||||
},
|
|
||||||
CHAR_IS_SIGNED,
|
|
||||||
Some("char"),
|
|
||||||
)?,
|
|
||||||
))
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
use core::ffi::*;
|
|
||||||
|
|
||||||
use libffi::middle::Type;
|
|
||||||
use mlua::prelude::*;
|
|
||||||
|
|
||||||
use super::super::c_type::{CType, CTypeCast, CTypeConvert};
|
|
||||||
use num::cast::AsPrimitive;
|
|
||||||
|
|
||||||
impl CTypeConvert for CType<c_double> {
|
|
||||||
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()> {
|
|
||||||
let value: c_double = match value {
|
|
||||||
LuaValue::Integer(t) => t.as_(),
|
|
||||||
LuaValue::Number(t) => t.as_(),
|
|
||||||
LuaValue::String(t) => t
|
|
||||||
.to_string_lossy()
|
|
||||||
.parse::<c_double>()
|
|
||||||
.map_err(LuaError::external)?,
|
|
||||||
_ => {
|
|
||||||
return Err(LuaError::external(format!(
|
|
||||||
"Argument LuaValue expected a Integer, Number or String, got {}",
|
|
||||||
value.type_name()
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
unsafe {
|
|
||||||
*(ptr.cast::<c_double>()) = value;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn ptr_into_luavalue(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue> {
|
|
||||||
let value = unsafe { (*ptr.cast::<c_double>()).into_lua(lua)? };
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CTypeCast for CType<c_double> {
|
|
||||||
fn cast(
|
|
||||||
&self,
|
|
||||||
from_ctype: &LuaAnyUserData,
|
|
||||||
into_ctype: &LuaAnyUserData,
|
|
||||||
from: &LuaAnyUserData,
|
|
||||||
into: &LuaAnyUserData,
|
|
||||||
) -> LuaResult<()> {
|
|
||||||
self.try_cast_num::<c_double, c_float>(into_ctype, from, into)?
|
|
||||||
.or(self.try_cast_num::<c_double, c_double>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_double, c_char>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_double, c_long>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_double, c_int>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_double, c_longlong>(into_ctype, from, into)?)
|
|
||||||
.ok_or_else(|| self.cast_failed_with(from_ctype, into_ctype))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
|
||||||
Ok((
|
|
||||||
"double",
|
|
||||||
CType::<c_double>::new_with_libffi_type(lua, Type::f64(), true, Some("double"))?,
|
|
||||||
))
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
use core::ffi::*;
|
|
||||||
|
|
||||||
use libffi::middle::Type;
|
|
||||||
use mlua::prelude::*;
|
|
||||||
|
|
||||||
use super::super::c_type::{CType, CTypeCast, CTypeConvert};
|
|
||||||
use num::cast::AsPrimitive;
|
|
||||||
|
|
||||||
impl CTypeConvert for CType<c_float> {
|
|
||||||
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()> {
|
|
||||||
let value: c_float = match value {
|
|
||||||
LuaValue::Integer(t) => t.as_(),
|
|
||||||
LuaValue::Number(t) => t.as_(),
|
|
||||||
LuaValue::String(t) => t
|
|
||||||
.to_string_lossy()
|
|
||||||
.parse::<c_float>()
|
|
||||||
.map_err(LuaError::external)?,
|
|
||||||
_ => {
|
|
||||||
return Err(LuaError::external(format!(
|
|
||||||
"Argument LuaValue expected a Integer, Number or String, got {}",
|
|
||||||
value.type_name()
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
unsafe {
|
|
||||||
*(ptr.cast::<c_float>()) = value;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn ptr_into_luavalue(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue> {
|
|
||||||
let value = unsafe { (*ptr.cast::<c_float>()).into_lua(lua)? };
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CTypeCast for CType<c_float> {
|
|
||||||
fn cast(
|
|
||||||
&self,
|
|
||||||
from_ctype: &LuaAnyUserData,
|
|
||||||
into_ctype: &LuaAnyUserData,
|
|
||||||
from: &LuaAnyUserData,
|
|
||||||
into: &LuaAnyUserData,
|
|
||||||
) -> LuaResult<()> {
|
|
||||||
self.try_cast_num::<c_float, c_float>(into_ctype, from, into)?
|
|
||||||
.or(self.try_cast_num::<c_float, c_double>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_float, c_char>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_float, c_long>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_float, c_int>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_float, c_longlong>(into_ctype, from, into)?)
|
|
||||||
.ok_or_else(|| self.cast_failed_with(from_ctype, into_ctype))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
|
||||||
Ok((
|
|
||||||
"float",
|
|
||||||
CType::<c_float>::new_with_libffi_type(lua, Type::f32(), true, Some("float"))?,
|
|
||||||
))
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
use core::ffi::*;
|
|
||||||
|
|
||||||
use libffi::middle::Type;
|
|
||||||
use mlua::prelude::*;
|
|
||||||
use num::cast::AsPrimitive;
|
|
||||||
|
|
||||||
use super::super::c_type::{CType, CTypeCast, CTypeConvert};
|
|
||||||
|
|
||||||
impl CTypeConvert for CType<c_int> {
|
|
||||||
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()> {
|
|
||||||
let value: c_int = match value {
|
|
||||||
LuaValue::Integer(t) => t.as_(),
|
|
||||||
LuaValue::Number(t) => t.as_(),
|
|
||||||
LuaValue::String(t) => t
|
|
||||||
.to_string_lossy()
|
|
||||||
.parse::<i32>()
|
|
||||||
.map_err(LuaError::external)?,
|
|
||||||
_ => {
|
|
||||||
return Err(LuaError::external(format!(
|
|
||||||
"Argument LuaValue expected a Integer, Number or String, got {}",
|
|
||||||
value.type_name()
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
unsafe {
|
|
||||||
*(ptr.cast::<c_int>()) = value;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn ptr_into_luavalue(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue> {
|
|
||||||
let value = unsafe { (*ptr.cast::<c_int>()).into_lua(lua)? };
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CType<c_int> {}
|
|
||||||
|
|
||||||
impl CTypeCast for CType<c_int> {
|
|
||||||
fn cast(
|
|
||||||
&self,
|
|
||||||
from_ctype: &LuaAnyUserData,
|
|
||||||
into_ctype: &LuaAnyUserData,
|
|
||||||
from: &LuaAnyUserData,
|
|
||||||
into: &LuaAnyUserData,
|
|
||||||
) -> LuaResult<()> {
|
|
||||||
self.try_cast_num::<c_int, c_float>(into_ctype, from, into)?
|
|
||||||
.or(self.try_cast_num::<c_int, c_double>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_int, c_char>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_int, c_long>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_int, c_int>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_int, c_longlong>(into_ctype, from, into)?)
|
|
||||||
.ok_or_else(|| self.cast_failed_with(from_ctype, into_ctype))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
|
||||||
Ok((
|
|
||||||
"int",
|
|
||||||
CType::<c_int>::new_with_libffi_type(
|
|
||||||
lua,
|
|
||||||
Type::c_int(),
|
|
||||||
c_int::MIN.unsigned_abs() != 0,
|
|
||||||
Some("int"),
|
|
||||||
)?,
|
|
||||||
))
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
use core::ffi::*;
|
|
||||||
|
|
||||||
use libffi::middle::Type;
|
|
||||||
use mlua::prelude::*;
|
|
||||||
|
|
||||||
use super::super::c_type::{CType, CTypeCast, CTypeConvert};
|
|
||||||
use num::cast::AsPrimitive;
|
|
||||||
|
|
||||||
impl CTypeConvert for CType<c_long> {
|
|
||||||
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()> {
|
|
||||||
let value: c_long = match value {
|
|
||||||
LuaValue::Integer(t) => t.as_(),
|
|
||||||
LuaValue::Number(t) => t.as_(),
|
|
||||||
LuaValue::String(t) => t
|
|
||||||
.to_string_lossy()
|
|
||||||
.parse::<c_long>()
|
|
||||||
.map_err(LuaError::external)?,
|
|
||||||
_ => {
|
|
||||||
return Err(LuaError::external(format!(
|
|
||||||
"Argument LuaValue expected a Integer, Number or String, got {}",
|
|
||||||
value.type_name()
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
unsafe {
|
|
||||||
*(ptr.cast::<c_long>()) = value;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn ptr_into_luavalue(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue> {
|
|
||||||
let value = unsafe { (*ptr.cast::<c_long>()).into_lua(lua)? };
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CTypeCast for CType<c_long> {
|
|
||||||
fn cast(
|
|
||||||
&self,
|
|
||||||
from_ctype: &LuaAnyUserData,
|
|
||||||
into_ctype: &LuaAnyUserData,
|
|
||||||
from: &LuaAnyUserData,
|
|
||||||
into: &LuaAnyUserData,
|
|
||||||
) -> LuaResult<()> {
|
|
||||||
self.try_cast_num::<c_long, c_float>(into_ctype, from, into)?
|
|
||||||
.or(self.try_cast_num::<c_long, c_double>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_long, c_char>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_long, c_long>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_long, c_int>(into_ctype, from, into)?)
|
|
||||||
.or(self.try_cast_num::<c_long, c_longlong>(into_ctype, from, into)?)
|
|
||||||
.ok_or_else(|| self.cast_failed_with(from_ctype, into_ctype))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
|
||||||
Ok((
|
|
||||||
"long",
|
|
||||||
CType::<c_long>::new_with_libffi_type(lua, Type::c_long(), true, Some("long"))?,
|
|
||||||
))
|
|
||||||
}
|
|
57
crates/lune-std-ffi/src/c/types/f32.rs
Normal file
57
crates/lune-std-ffi/src/c/types/f32.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeSignedness};
|
||||||
|
use crate::ffi::ffi_native::NativeConvert;
|
||||||
|
|
||||||
|
impl CTypeSignedness for CType<f32> {
|
||||||
|
fn get_signedness(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeConvert for CType<f32> {
|
||||||
|
fn luavalue_into_ptr<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
_lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
let value: f32 = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<f32>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<f32>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let value = unsafe { (*ptr.cast::<f32>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_type(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"f32",
|
||||||
|
CType::<f32>::new_with_libffi_type(lua, Type::f32(), Some("f32"))?,
|
||||||
|
))
|
||||||
|
}
|
57
crates/lune-std-ffi/src/c/types/f64.rs
Normal file
57
crates/lune-std-ffi/src/c/types/f64.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeSignedness};
|
||||||
|
use crate::ffi::ffi_native::NativeConvert;
|
||||||
|
|
||||||
|
impl CTypeSignedness for CType<f64> {
|
||||||
|
fn get_signedness(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeConvert for CType<f64> {
|
||||||
|
fn luavalue_into_ptr<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
_lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
let value: f64 = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<f64>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<f64>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let value = unsafe { (*ptr.cast::<f64>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_type(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"f64",
|
||||||
|
CType::<f64>::new_with_libffi_type(lua, Type::f64(), Some("f64"))?,
|
||||||
|
))
|
||||||
|
}
|
61
crates/lune-std-ffi/src/c/types/i128.rs
Normal file
61
crates/lune-std-ffi/src/c/types/i128.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeSignedness};
|
||||||
|
use crate::ffi::ffi_native::NativeConvert;
|
||||||
|
|
||||||
|
impl CTypeSignedness for CType<i128> {
|
||||||
|
fn get_signedness(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeConvert for CType<i128> {
|
||||||
|
fn luavalue_into_ptr<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
_lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
let value: i128 = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<i128>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<i128>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let value = unsafe { (*ptr.cast::<i128>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_type(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"i128",
|
||||||
|
CType::<i128>::new_with_libffi_type(
|
||||||
|
lua,
|
||||||
|
Type::structure(vec![Type::u64(), Type::u64()]),
|
||||||
|
Some("i128"),
|
||||||
|
)?,
|
||||||
|
))
|
||||||
|
}
|
57
crates/lune-std-ffi/src/c/types/i16.rs
Normal file
57
crates/lune-std-ffi/src/c/types/i16.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeSignedness};
|
||||||
|
use crate::ffi::ffi_native::NativeConvert;
|
||||||
|
|
||||||
|
impl CTypeSignedness for CType<i16> {
|
||||||
|
fn get_signedness(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeConvert for CType<i16> {
|
||||||
|
fn luavalue_into_ptr<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
_lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
let value: i16 = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<i16>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<i16>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let value = unsafe { (*ptr.cast::<i16>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_type(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"i16",
|
||||||
|
CType::<i16>::new_with_libffi_type(lua, Type::i16(), Some("f32"))?,
|
||||||
|
))
|
||||||
|
}
|
57
crates/lune-std-ffi/src/c/types/i32.rs
Normal file
57
crates/lune-std-ffi/src/c/types/i32.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeSignedness};
|
||||||
|
use crate::ffi::ffi_native::NativeConvert;
|
||||||
|
|
||||||
|
impl CTypeSignedness for CType<i32> {
|
||||||
|
fn get_signedness(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeConvert for CType<i32> {
|
||||||
|
fn luavalue_into_ptr<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
_lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
let value: i32 = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<i32>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<i32>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let value = unsafe { (*ptr.cast::<i32>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_type(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"i32",
|
||||||
|
CType::<i32>::new_with_libffi_type(lua, Type::i32(), Some("i32"))?,
|
||||||
|
))
|
||||||
|
}
|
57
crates/lune-std-ffi/src/c/types/i64.rs
Normal file
57
crates/lune-std-ffi/src/c/types/i64.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeSignedness};
|
||||||
|
use crate::ffi::ffi_native::NativeConvert;
|
||||||
|
|
||||||
|
impl CTypeSignedness for CType<i64> {
|
||||||
|
fn get_signedness(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeConvert for CType<i64> {
|
||||||
|
fn luavalue_into_ptr<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
_lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
let value: i64 = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<i64>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<i64>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let value = unsafe { (*ptr.cast::<i64>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_type(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"i64",
|
||||||
|
CType::<i64>::new_with_libffi_type(lua, Type::i64(), Some("i64"))?,
|
||||||
|
))
|
||||||
|
}
|
53
crates/lune-std-ffi/src/c/types/i8.rs
Normal file
53
crates/lune-std-ffi/src/c/types/i8.rs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeSignedness};
|
||||||
|
use crate::ffi::ffi_native::NativeConvert;
|
||||||
|
|
||||||
|
impl CTypeSignedness for CType<i8> {
|
||||||
|
fn get_signedness(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeConvert for CType<i8> {
|
||||||
|
fn luavalue_into_ptr<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
_lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
let value: i8 = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t.as_bytes().first().map_or(0, u8::to_owned).as_(),
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<i8>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let value = unsafe { (*ptr.cast::<i8>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_type(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"i8",
|
||||||
|
CType::<i8>::new_with_libffi_type(lua, Type::i8(), Some("i8"))?,
|
||||||
|
))
|
||||||
|
}
|
57
crates/lune-std-ffi/src/c/types/isize.rs
Normal file
57
crates/lune-std-ffi/src/c/types/isize.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeSignedness};
|
||||||
|
use crate::ffi::ffi_native::NativeConvert;
|
||||||
|
|
||||||
|
impl CTypeSignedness for CType<isize> {
|
||||||
|
fn get_signedness(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeConvert for CType<isize> {
|
||||||
|
fn luavalue_into_ptr<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
_lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
let value: isize = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<isize>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<isize>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let value = unsafe { (*ptr.cast::<isize>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_type(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"isize",
|
||||||
|
CType::<isize>::new_with_libffi_type(lua, Type::isize(), Some("isize"))?,
|
||||||
|
))
|
||||||
|
}
|
|
@ -1,18 +1,156 @@
|
||||||
mod c_char;
|
use core::ffi::*;
|
||||||
mod c_double;
|
use std::any::TypeId;
|
||||||
mod c_float;
|
|
||||||
mod c_int;
|
|
||||||
mod c_long;
|
|
||||||
|
|
||||||
|
use libffi::middle::Type;
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::c_type::CType;
|
||||||
|
use super::c_type::CTypeCast;
|
||||||
|
|
||||||
|
pub mod f32;
|
||||||
|
pub mod f64;
|
||||||
|
pub mod i128;
|
||||||
|
pub mod i16;
|
||||||
|
pub mod i32;
|
||||||
|
pub mod i64;
|
||||||
|
pub mod i8;
|
||||||
|
pub mod isize;
|
||||||
|
pub mod u128;
|
||||||
|
pub mod u16;
|
||||||
|
pub mod u32;
|
||||||
|
pub mod u64;
|
||||||
|
pub mod u8;
|
||||||
|
pub mod usize;
|
||||||
|
|
||||||
|
impl<T> CTypeCast for CType<T>
|
||||||
|
where
|
||||||
|
T: AsPrimitive<u8>
|
||||||
|
+ AsPrimitive<u16>
|
||||||
|
+ AsPrimitive<u32>
|
||||||
|
+ AsPrimitive<u64>
|
||||||
|
+ AsPrimitive<u128>
|
||||||
|
+ AsPrimitive<i8>
|
||||||
|
+ AsPrimitive<i16>
|
||||||
|
+ AsPrimitive<i32>
|
||||||
|
+ AsPrimitive<i64>
|
||||||
|
+ AsPrimitive<i128>
|
||||||
|
+ AsPrimitive<f32>
|
||||||
|
+ AsPrimitive<f64>
|
||||||
|
+ AsPrimitive<usize>
|
||||||
|
+ AsPrimitive<isize>,
|
||||||
|
{
|
||||||
|
fn cast(
|
||||||
|
&self,
|
||||||
|
from_ctype: &LuaAnyUserData,
|
||||||
|
into_ctype: &LuaAnyUserData,
|
||||||
|
from: &LuaAnyUserData,
|
||||||
|
into: &LuaAnyUserData,
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
self.try_cast_num::<T, u8>(into_ctype, from, into)?
|
||||||
|
.or(self.try_cast_num::<T, u16>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<T, u32>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<T, u64>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<T, u128>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<T, i8>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<T, i16>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<T, i32>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<T, i64>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<T, i128>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<T, f32>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<T, f64>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<T, usize>(into_ctype, from, into)?)
|
||||||
|
.or(self.try_cast_num::<T, isize>(into_ctype, from, into)?)
|
||||||
|
.ok_or_else(|| self.cast_failed_with(from_ctype, into_ctype))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// export all default c-types
|
||||||
|
pub fn create_all_c_types(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaAnyUserData)>> {
|
||||||
|
Ok(vec![
|
||||||
|
(
|
||||||
|
"char",
|
||||||
|
CType::<c_char>::new_with_libffi_type(
|
||||||
|
lua,
|
||||||
|
if TypeId::of::<c_char>() == TypeId::of::<u8>() {
|
||||||
|
Type::c_uchar()
|
||||||
|
} else {
|
||||||
|
Type::c_schar()
|
||||||
|
},
|
||||||
|
Some("longlong"),
|
||||||
|
)?,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"uchar",
|
||||||
|
CType::<c_uchar>::new_with_libffi_type(lua, Type::c_uchar(), Some("uchar"))?,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"schar",
|
||||||
|
CType::<c_schar>::new_with_libffi_type(lua, Type::c_schar(), Some("schar"))?,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"short",
|
||||||
|
CType::<c_short>::new_with_libffi_type(lua, Type::c_short(), Some("short"))?,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ushort",
|
||||||
|
CType::<c_ushort>::new_with_libffi_type(lua, Type::c_ushort(), Some("ushort"))?,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"int",
|
||||||
|
CType::<c_int>::new_with_libffi_type(lua, Type::c_int(), Some("int"))?,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"uint",
|
||||||
|
CType::<c_uint>::new_with_libffi_type(lua, Type::c_uint(), Some("uint"))?,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"long",
|
||||||
|
CType::<c_long>::new_with_libffi_type(lua, Type::c_long(), Some("long"))?,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ulong",
|
||||||
|
CType::<c_ulong>::new_with_libffi_type(lua, Type::c_ulong(), Some("ulong"))?,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"longlong",
|
||||||
|
CType::<c_longlong>::new_with_libffi_type(lua, Type::c_longlong(), Some("longlong"))?,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"ulonglong",
|
||||||
|
CType::<c_ulonglong>::new_with_libffi_type(
|
||||||
|
lua,
|
||||||
|
Type::c_ulonglong(),
|
||||||
|
Some("ulonglong"),
|
||||||
|
)?,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"float",
|
||||||
|
CType::<c_float>::new_with_libffi_type(lua, Type::f32(), Some("float"))?,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"double",
|
||||||
|
CType::<c_double>::new_with_libffi_type(lua, Type::f64(), Some("double"))?,
|
||||||
|
),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
// export all default c-types
|
// export all default c-types
|
||||||
pub fn create_all_types(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaAnyUserData)>> {
|
pub fn create_all_types(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaAnyUserData)>> {
|
||||||
Ok(vec![
|
Ok(vec![
|
||||||
c_char::get_export(lua)?,
|
self::u8::create_type(lua)?,
|
||||||
c_double::get_export(lua)?,
|
self::u16::create_type(lua)?,
|
||||||
c_float::get_export(lua)?,
|
self::u32::create_type(lua)?,
|
||||||
c_int::get_export(lua)?,
|
self::u64::create_type(lua)?,
|
||||||
c_long::get_export(lua)?,
|
self::u128::create_type(lua)?,
|
||||||
|
self::i8::create_type(lua)?,
|
||||||
|
self::i16::create_type(lua)?,
|
||||||
|
self::i32::create_type(lua)?,
|
||||||
|
self::i64::create_type(lua)?,
|
||||||
|
self::i128::create_type(lua)?,
|
||||||
|
self::f64::create_type(lua)?,
|
||||||
|
self::f32::create_type(lua)?,
|
||||||
|
self::usize::create_type(lua)?,
|
||||||
|
self::isize::create_type(lua)?,
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
61
crates/lune-std-ffi/src/c/types/u128.rs
Normal file
61
crates/lune-std-ffi/src/c/types/u128.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeSignedness};
|
||||||
|
use crate::ffi::ffi_native::NativeConvert;
|
||||||
|
|
||||||
|
impl CTypeSignedness for CType<u128> {
|
||||||
|
fn get_signedness(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeConvert for CType<u128> {
|
||||||
|
fn luavalue_into_ptr<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
_lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
let value: u128 = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<u128>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<u128>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let value = unsafe { (*ptr.cast::<u128>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_type(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"u128",
|
||||||
|
CType::<u128>::new_with_libffi_type(
|
||||||
|
lua,
|
||||||
|
Type::structure(vec![Type::u64(), Type::u64()]),
|
||||||
|
Some("u128"),
|
||||||
|
)?,
|
||||||
|
))
|
||||||
|
}
|
58
crates/lune-std-ffi/src/c/types/u16.rs
Normal file
58
crates/lune-std-ffi/src/c/types/u16.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeSignedness};
|
||||||
|
use crate::ffi::ffi_native::NativeConvert;
|
||||||
|
|
||||||
|
impl CTypeSignedness for CType<u16> {
|
||||||
|
fn get_signedness(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeConvert for CType<u16> {
|
||||||
|
// Convert luavalue into data, then write into ptr
|
||||||
|
fn luavalue_into_ptr<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
_lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
let value: u16 = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<u16>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<u16>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let value = unsafe { (*ptr.cast::<u16>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_type(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"u16",
|
||||||
|
CType::<u16>::new_with_libffi_type(lua, Type::u16(), Some("u16"))?,
|
||||||
|
))
|
||||||
|
}
|
57
crates/lune-std-ffi/src/c/types/u32.rs
Normal file
57
crates/lune-std-ffi/src/c/types/u32.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeSignedness};
|
||||||
|
use crate::ffi::ffi_native::NativeConvert;
|
||||||
|
|
||||||
|
impl CTypeSignedness for CType<u32> {
|
||||||
|
fn get_signedness(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeConvert for CType<u32> {
|
||||||
|
fn luavalue_into_ptr<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
_lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
let value: u32 = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<u32>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<u32>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let value = unsafe { (*ptr.cast::<u32>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_type(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"u32",
|
||||||
|
CType::<u32>::new_with_libffi_type(lua, Type::u32(), Some("u32"))?,
|
||||||
|
))
|
||||||
|
}
|
57
crates/lune-std-ffi/src/c/types/u64.rs
Normal file
57
crates/lune-std-ffi/src/c/types/u64.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeSignedness};
|
||||||
|
use crate::ffi::ffi_native::NativeConvert;
|
||||||
|
|
||||||
|
impl CTypeSignedness for CType<u64> {
|
||||||
|
fn get_signedness(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeConvert for CType<u64> {
|
||||||
|
fn luavalue_into_ptr<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
_lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
let value: u64 = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<u64>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<u64>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let value = unsafe { (*ptr.cast::<u64>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_type(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"u64",
|
||||||
|
CType::<u64>::new_with_libffi_type(lua, Type::u64(), Some("u64"))?,
|
||||||
|
))
|
||||||
|
}
|
56
crates/lune-std-ffi/src/c/types/u8.rs
Normal file
56
crates/lune-std-ffi/src/c/types/u8.rs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeSignedness};
|
||||||
|
use crate::ffi::ffi_native::NativeConvert;
|
||||||
|
|
||||||
|
impl CTypeSignedness for CType<u8> {
|
||||||
|
fn get_signedness(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeConvert for CType<u8> {
|
||||||
|
// Convert luavalue into data, then write into ptr
|
||||||
|
fn luavalue_into_ptr<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
_lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
let value: u8 = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t.as_bytes().first().map_or(0, u8::to_owned).as_(),
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<u8>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read data from ptr, then convert into luavalue
|
||||||
|
fn ptr_into_luavalue<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let value = unsafe { (*ptr.cast::<u8>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_type(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"u8",
|
||||||
|
CType::<u8>::new_with_libffi_type(lua, Type::u8(), Some("u8"))?,
|
||||||
|
))
|
||||||
|
}
|
57
crates/lune-std-ffi/src/c/types/usize.rs
Normal file
57
crates/lune-std-ffi/src/c/types/usize.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeSignedness};
|
||||||
|
use crate::ffi::ffi_native::NativeConvert;
|
||||||
|
|
||||||
|
impl CTypeSignedness for CType<usize> {
|
||||||
|
fn get_signedness(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeConvert for CType<usize> {
|
||||||
|
fn luavalue_into_ptr<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
_lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
let value: usize = match value {
|
||||||
|
LuaValue::Integer(t) => t.as_(),
|
||||||
|
LuaValue::Number(t) => t.as_(),
|
||||||
|
LuaValue::String(t) => t
|
||||||
|
.to_string_lossy()
|
||||||
|
.parse::<usize>()
|
||||||
|
.map_err(LuaError::external)?,
|
||||||
|
_ => {
|
||||||
|
return Err(LuaError::external(format!(
|
||||||
|
"Argument LuaValue expected a Integer, Number or String, got {}",
|
||||||
|
value.type_name()
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<usize>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue<'lua>(
|
||||||
|
&self,
|
||||||
|
_this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let value = unsafe { (*ptr.cast::<usize>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_type(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"usize",
|
||||||
|
CType::<usize>::new_with_libffi_type(lua, Type::usize(), Some("usize"))?,
|
||||||
|
))
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
#![allow(clippy::cargo_common_metadata)]
|
#![allow(clippy::cargo_common_metadata)]
|
||||||
|
|
||||||
|
use mlua::prelude::*;
|
||||||
|
|
||||||
// This is a small library that helps you set the dependencies of data in Lua.
|
// This is a small library that helps you set the dependencies of data in Lua.
|
||||||
// In FFI, there is often data that is dependent on other data.
|
// In FFI, there is often data that is dependent on other data.
|
||||||
// However, if you use user_value to inform Lua of the dependency,
|
// However, if you use user_value to inform Lua of the dependency,
|
||||||
|
@ -22,7 +24,6 @@
|
||||||
// Since the outermost pointer holds the definition for the pointer
|
// Since the outermost pointer holds the definition for the pointer
|
||||||
// type inside it, only the outermost type will be removed on the first gc.
|
// type inside it, only the outermost type will be removed on the first gc.
|
||||||
// It doesn't matter much. But if there is a cleaner way, we should choose it
|
// It doesn't matter much. But if there is a cleaner way, we should choose it
|
||||||
use mlua::prelude::*;
|
|
||||||
|
|
||||||
// Forces 'associated' to persist as long as 'value' is alive.
|
// Forces 'associated' to persist as long as 'value' is alive.
|
||||||
// 'value' can only hold one value. If you want to keep something else,
|
// 'value' can only hold one value. If you want to keep something else,
|
||||||
|
|
|
@ -1,5 +1,22 @@
|
||||||
#![allow(clippy::cargo_common_metadata)]
|
#![allow(clippy::cargo_common_metadata)]
|
||||||
|
|
||||||
|
use std::boxed::Box;
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
use super::association_names::REF_INNER;
|
||||||
|
use super::ffi_association::set_association;
|
||||||
|
use super::ffi_ref::{FfiRef, FfiRefBounds, FfiRefFlag, FfiRefFlagList};
|
||||||
|
|
||||||
|
static BOX_REF_FLAGS: LazyLock<FfiRefFlagList> = LazyLock::new(|| {
|
||||||
|
FfiRefFlagList::new(&[
|
||||||
|
FfiRefFlag::Offsetable,
|
||||||
|
FfiRefFlag::Readable,
|
||||||
|
FfiRefFlag::Writable,
|
||||||
|
])
|
||||||
|
});
|
||||||
|
|
||||||
// It is an untyped, sized memory area that Lua can manage.
|
// It is an untyped, sized memory area that Lua can manage.
|
||||||
// This area is safe within Lua. Operations have their boundaries checked.
|
// This area is safe within Lua. Operations have their boundaries checked.
|
||||||
// It is basically intended to implement passing a pointed space to the outside.
|
// It is basically intended to implement passing a pointed space to the outside.
|
||||||
|
@ -9,15 +26,6 @@
|
||||||
// rather, it creates more heap space, so it should be used appropriately
|
// rather, it creates more heap space, so it should be used appropriately
|
||||||
// where necessary.
|
// where necessary.
|
||||||
|
|
||||||
use std::boxed::Box;
|
|
||||||
|
|
||||||
use mlua::prelude::*;
|
|
||||||
|
|
||||||
use super::association_names::REF_INNER;
|
|
||||||
use super::ffi_association::set_association;
|
|
||||||
use super::ffi_bounds::FfiRefBounds;
|
|
||||||
use super::ffi_ref::FfiRef;
|
|
||||||
|
|
||||||
pub struct FfiBox(Box<[u8]>);
|
pub struct FfiBox(Box<[u8]>);
|
||||||
|
|
||||||
impl FfiBox {
|
impl FfiBox {
|
||||||
|
@ -73,7 +81,8 @@ impl FfiBox {
|
||||||
// To deref a box space is to allow lua to read any space,
|
// To deref a box space is to allow lua to read any space,
|
||||||
// which has security issues and is ultimately dangerous.
|
// which has security issues and is ultimately dangerous.
|
||||||
// Therefore, box:ref():deref() is not allowed.
|
// Therefore, box:ref():deref() is not allowed.
|
||||||
let luaref = lua.create_userdata(FfiRef::new(ptr.cast(), false, Some(bounds)))?;
|
let luaref =
|
||||||
|
lua.create_userdata(FfiRef::new(ptr.cast(), (*BOX_REF_FLAGS).clone(), bounds))?;
|
||||||
|
|
||||||
// Makes box alive longer then ref
|
// Makes box alive longer then ref
|
||||||
set_association(lua, REF_INNER, &luaref, &this)?;
|
set_association(lua, REF_INNER, &luaref, &this)?;
|
||||||
|
|
|
@ -34,3 +34,23 @@ pub unsafe fn get_ptr_from_userdata(
|
||||||
|
|
||||||
Ok(ptr)
|
Ok(ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub mod bit_mask {
|
||||||
|
pub const U8_MASK1: u8 = 1;
|
||||||
|
pub const U8_MASK2: u8 = 2;
|
||||||
|
pub const U8_MASK3: u8 = 4;
|
||||||
|
pub const U8_MASK4: u8 = 8;
|
||||||
|
pub const U8_MASK5: u8 = 16;
|
||||||
|
pub const U8_MASK6: u8 = 32;
|
||||||
|
pub const U8_MASK7: u8 = 64;
|
||||||
|
pub const U8_MASK8: u8 = 128;
|
||||||
|
|
||||||
|
macro_rules! U8_TEST {
|
||||||
|
($val:expr, $mask:ident) => {
|
||||||
|
($val & $mask != 0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use U8_TEST;
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,20 @@
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
use dlopen2::symbor::Library;
|
use dlopen2::symbor::Library;
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
|
||||||
use super::ffi_association::set_association;
|
use super::ffi_association::set_association;
|
||||||
use super::ffi_ref::FfiRef;
|
use super::ffi_ref::{FfiRef, FfiRefFlag, FfiRefFlagList, UNSIZED_BOUNDS};
|
||||||
|
|
||||||
|
static LIB_REF_FLAGS: LazyLock<FfiRefFlagList> = LazyLock::new(|| {
|
||||||
|
FfiRefFlagList::new(&[
|
||||||
|
FfiRefFlag::Offsetable,
|
||||||
|
FfiRefFlag::Readable,
|
||||||
|
FfiRefFlag::Dereferenceable,
|
||||||
|
FfiRefFlag::Function,
|
||||||
|
])
|
||||||
|
});
|
||||||
|
|
||||||
pub struct FfiLib(Library);
|
pub struct FfiLib(Library);
|
||||||
|
|
||||||
|
@ -39,7 +49,11 @@ impl FfiLib {
|
||||||
.map_err(|err| LuaError::external(format!("{err}")))?
|
.map_err(|err| LuaError::external(format!("{err}")))?
|
||||||
};
|
};
|
||||||
|
|
||||||
let luasym = lua.create_userdata(FfiRef::new((*sym).cast(), true, None))?;
|
let luasym = lua.create_userdata(FfiRef::new(
|
||||||
|
(*sym).cast(),
|
||||||
|
(*LIB_REF_FLAGS).clone(),
|
||||||
|
UNSIZED_BOUNDS,
|
||||||
|
))?;
|
||||||
|
|
||||||
set_association(lua, SYM_INNER, &luasym, &this)?;
|
set_association(lua, SYM_INNER, &luasym, &this)?;
|
||||||
|
|
||||||
|
|
24
crates/lune-std-ffi/src/ffi/ffi_native/cast.rs
Normal file
24
crates/lune-std-ffi/src/ffi/ffi_native/cast.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#![allow(clippy::cargo_common_metadata)]
|
||||||
|
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use num::cast::AsPrimitive;
|
||||||
|
|
||||||
|
use super::super::ffi_helper::get_ptr_from_userdata;
|
||||||
|
|
||||||
|
pub trait NativeCast {
|
||||||
|
// Cast T as U
|
||||||
|
fn cast_num<T, U>(&self, from: &LuaAnyUserData, into: &LuaAnyUserData) -> LuaResult<()>
|
||||||
|
where
|
||||||
|
T: AsPrimitive<U>,
|
||||||
|
U: 'static + Copy,
|
||||||
|
{
|
||||||
|
let from_ptr = unsafe { get_ptr_from_userdata(from, None)?.cast::<T>() };
|
||||||
|
let into_ptr = unsafe { get_ptr_from_userdata(into, None)?.cast::<U>() };
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
*into_ptr = (*from_ptr).as_();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
52
crates/lune-std-ffi/src/ffi/ffi_native/convert.rs
Normal file
52
crates/lune-std-ffi/src/ffi/ffi_native/convert.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#![allow(clippy::cargo_common_metadata)]
|
||||||
|
|
||||||
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
use super::super::ffi_helper::get_ptr_from_userdata;
|
||||||
|
|
||||||
|
// Handle native data, provide type conversion between luavalue and native types
|
||||||
|
pub trait NativeConvert {
|
||||||
|
// Convert luavalue into data, then write into ptr
|
||||||
|
fn luavalue_into_ptr<'lua>(
|
||||||
|
&self,
|
||||||
|
this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
value: LuaValue<'lua>,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<()>;
|
||||||
|
|
||||||
|
// Read data from ptr, then convert into luavalue
|
||||||
|
fn ptr_into_luavalue<'lua>(
|
||||||
|
&self,
|
||||||
|
this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
ptr: *mut (),
|
||||||
|
) -> LuaResult<LuaValue<'lua>>;
|
||||||
|
|
||||||
|
// Read data from userdata (such as box or ref) and convert it into luavalue
|
||||||
|
unsafe fn read_userdata<'lua>(
|
||||||
|
&self,
|
||||||
|
this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
userdata: &LuaAnyUserData<'lua>,
|
||||||
|
offset: Option<isize>,
|
||||||
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
|
let ptr = unsafe { get_ptr_from_userdata(userdata, offset)? };
|
||||||
|
let value = Self::ptr_into_luavalue(self, this, lua, ptr)?;
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write data into userdata (such as box or ref) from luavalue
|
||||||
|
unsafe fn write_userdata<'lua>(
|
||||||
|
&self,
|
||||||
|
this: &LuaAnyUserData<'lua>,
|
||||||
|
lua: &'lua Lua,
|
||||||
|
luavalue: LuaValue<'lua>,
|
||||||
|
userdata: LuaAnyUserData<'lua>,
|
||||||
|
offset: Option<isize>,
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
let ptr = unsafe { get_ptr_from_userdata(&userdata, offset)? };
|
||||||
|
Self::luavalue_into_ptr(self, this, lua, luavalue, ptr)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
5
crates/lune-std-ffi/src/ffi/ffi_native/mod.rs
Normal file
5
crates/lune-std-ffi/src/ffi/ffi_native/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
mod cast;
|
||||||
|
mod convert;
|
||||||
|
|
||||||
|
pub use self::cast::NativeCast;
|
||||||
|
pub use self::convert::NativeConvert;
|
|
@ -1,11 +0,0 @@
|
||||||
use core::ffi::c_char;
|
|
||||||
use std::vec::Vec;
|
|
||||||
|
|
||||||
pub const CHAR_IS_SIGNED: bool = c_char::MIN as u8 != u8::MIN;
|
|
||||||
|
|
||||||
pub fn get_platform_value() -> Vec<(&'static str, &'static str)> {
|
|
||||||
vec![(
|
|
||||||
"char_variant",
|
|
||||||
if CHAR_IS_SIGNED { "schar" } else { "uchar" },
|
|
||||||
)]
|
|
||||||
}
|
|
|
@ -1,24 +1,36 @@
|
||||||
// Memory range for ref or box data. For boundary checking
|
// Memory range for ref or box data. For boundary checking
|
||||||
pub struct FfiRefBounds {
|
pub struct FfiRefBounds {
|
||||||
// Indicates how much data is above the pointer
|
// Indicates how much data is above the pointer
|
||||||
pub(crate) high: usize,
|
pub(crate) above: usize,
|
||||||
// Indicates how much data is below the pointer
|
// Indicates how much data is below the pointer
|
||||||
pub(crate) low: usize,
|
pub(crate) below: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const UNSIZED_BOUNDS: FfiRefBounds = FfiRefBounds {
|
||||||
|
above: usize::MAX,
|
||||||
|
below: usize::MAX,
|
||||||
|
};
|
||||||
|
|
||||||
impl FfiRefBounds {
|
impl FfiRefBounds {
|
||||||
pub fn new(high: usize, low: usize) -> Self {
|
pub fn new(above: usize, below: usize) -> Self {
|
||||||
Self { high, low }
|
Self { above, below }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_unsized(&self) -> bool {
|
||||||
|
self.above == usize::MAX && self.below == usize::MAX
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check boundary
|
// Check boundary
|
||||||
pub fn check(&self, offset: isize) -> bool {
|
pub fn check(&self, offset: isize) -> bool {
|
||||||
|
if self.is_unsized() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
let sign = offset.signum();
|
let sign = offset.signum();
|
||||||
let offset_abs = offset.unsigned_abs();
|
let offset_abs = offset.unsigned_abs();
|
||||||
if sign == -1 {
|
if sign == -1 {
|
||||||
self.high >= offset_abs
|
self.above >= offset_abs
|
||||||
} else if sign == 1 {
|
} else if sign == 1 {
|
||||||
self.low >= offset_abs
|
self.below >= offset_abs
|
||||||
} else {
|
} else {
|
||||||
// sign == 0
|
// sign == 0
|
||||||
true
|
true
|
||||||
|
@ -27,13 +39,16 @@ impl FfiRefBounds {
|
||||||
|
|
||||||
// Check boundary
|
// Check boundary
|
||||||
pub fn check_sized(&self, offset: isize, size: usize) -> bool {
|
pub fn check_sized(&self, offset: isize, size: usize) -> bool {
|
||||||
|
if self.is_unsized() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
let end = offset + (size as isize) - 1;
|
let end = offset + (size as isize) - 1;
|
||||||
let sign = end.signum();
|
let sign = end.signum();
|
||||||
let end_abs = end.unsigned_abs();
|
let end_abs = end.unsigned_abs();
|
||||||
if sign == -1 {
|
if sign == -1 {
|
||||||
self.high >= end_abs
|
self.above >= end_abs
|
||||||
} else if sign == 1 {
|
} else if sign == 1 {
|
||||||
self.low >= end_abs
|
self.below >= end_abs
|
||||||
} else {
|
} else {
|
||||||
// sign == 0
|
// sign == 0
|
||||||
true
|
true
|
||||||
|
@ -47,21 +62,24 @@ impl FfiRefBounds {
|
||||||
let offset_abs = offset.unsigned_abs();
|
let offset_abs = offset.unsigned_abs();
|
||||||
|
|
||||||
let high: usize = if sign == -1 {
|
let high: usize = if sign == -1 {
|
||||||
self.high - offset_abs
|
self.above - offset_abs
|
||||||
} else if sign == 1 {
|
} else if sign == 1 {
|
||||||
self.high + offset_abs
|
self.above + offset_abs
|
||||||
} else {
|
} else {
|
||||||
self.high
|
self.above
|
||||||
};
|
};
|
||||||
|
|
||||||
let low: usize = if sign == -1 {
|
let low: usize = if sign == -1 {
|
||||||
self.low + offset_abs
|
self.below + offset_abs
|
||||||
} else if sign == 1 {
|
} else if sign == 1 {
|
||||||
self.low - offset_abs
|
self.below - offset_abs
|
||||||
} else {
|
} else {
|
||||||
self.low
|
self.below
|
||||||
};
|
};
|
||||||
|
|
||||||
Self { high, low }
|
Self {
|
||||||
|
above: high,
|
||||||
|
below: low,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
71
crates/lune-std-ffi/src/ffi/ffi_ref/flags.rs
Normal file
71
crates/lune-std-ffi/src/ffi/ffi_ref/flags.rs
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
use super::super::ffi_helper::bit_mask::*;
|
||||||
|
|
||||||
|
pub enum FfiRefFlag {
|
||||||
|
Dereferenceable,
|
||||||
|
Readable,
|
||||||
|
Writable,
|
||||||
|
Offsetable,
|
||||||
|
Function,
|
||||||
|
}
|
||||||
|
impl FfiRefFlag {
|
||||||
|
pub const fn value(&self) -> u8 {
|
||||||
|
match self {
|
||||||
|
Self::Dereferenceable => U8_MASK1,
|
||||||
|
Self::Readable => U8_MASK2,
|
||||||
|
Self::Writable => U8_MASK3,
|
||||||
|
Self::Offsetable => U8_MASK4,
|
||||||
|
Self::Function => U8_MASK5,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FfiRefFlagList(u8);
|
||||||
|
#[allow(unused)]
|
||||||
|
impl FfiRefFlagList {
|
||||||
|
pub fn zero() -> Self {
|
||||||
|
Self(0)
|
||||||
|
}
|
||||||
|
pub fn new(flags: &[FfiRefFlag]) -> Self {
|
||||||
|
let mut value = 0;
|
||||||
|
for i in flags {
|
||||||
|
value |= i.value();
|
||||||
|
}
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
fn set(&mut self, value: bool, mask: u8) {
|
||||||
|
if value {
|
||||||
|
self.0 |= mask;
|
||||||
|
} else {
|
||||||
|
self.0 &= !mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn is_dereferenceable(&self) -> bool {
|
||||||
|
U8_TEST!(self.0, U8_MASK1)
|
||||||
|
}
|
||||||
|
pub fn set_dereferenceable(&mut self, value: bool) {
|
||||||
|
self.set(value, U8_MASK1);
|
||||||
|
}
|
||||||
|
pub fn is_readable(&self) -> bool {
|
||||||
|
U8_TEST!(self.0, U8_MASK2)
|
||||||
|
}
|
||||||
|
pub fn set_readable(&mut self, value: bool) {
|
||||||
|
self.set(value, U8_MASK2);
|
||||||
|
}
|
||||||
|
pub fn is_writable(&self) -> bool {
|
||||||
|
U8_TEST!(self.0, U8_MASK3)
|
||||||
|
}
|
||||||
|
pub fn set_writable(&mut self, value: bool) {
|
||||||
|
self.set(value, U8_MASK2);
|
||||||
|
}
|
||||||
|
pub fn is_offsetable(&self) -> bool {
|
||||||
|
U8_TEST!(self.0, U8_MASK4)
|
||||||
|
}
|
||||||
|
pub fn set_offsetable(&mut self, value: bool) {
|
||||||
|
self.set(value, U8_MASK2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Clone for FfiRefFlagList {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self(self.0)
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,12 @@ use mlua::prelude::*;
|
||||||
|
|
||||||
use super::association_names::REF_INNER;
|
use super::association_names::REF_INNER;
|
||||||
use super::ffi_association::{get_association, set_association};
|
use super::ffi_association::{get_association, set_association};
|
||||||
use super::ffi_bounds::FfiRefBounds;
|
|
||||||
|
mod bounds;
|
||||||
|
mod flags;
|
||||||
|
|
||||||
|
pub use self::bounds::{FfiRefBounds, UNSIZED_BOUNDS};
|
||||||
|
pub use self::flags::{FfiRefFlag, FfiRefFlagList};
|
||||||
|
|
||||||
// A referenced space. It is possible to read and write through types.
|
// A referenced space. It is possible to read and write through types.
|
||||||
// This operation is not safe. This may cause a memory error in Lua
|
// This operation is not safe. This may cause a memory error in Lua
|
||||||
|
@ -16,16 +21,16 @@ use super::ffi_bounds::FfiRefBounds;
|
||||||
|
|
||||||
pub struct FfiRef {
|
pub struct FfiRef {
|
||||||
ptr: *mut (),
|
ptr: *mut (),
|
||||||
dereferenceable: bool,
|
flags: FfiRefFlagList,
|
||||||
range: Option<FfiRefBounds>,
|
boundary: FfiRefBounds,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FfiRef {
|
impl FfiRef {
|
||||||
pub fn new(ptr: *mut (), dereferenceable: bool, range: Option<FfiRefBounds>) -> Self {
|
pub fn new(ptr: *mut (), flags: FfiRefFlagList, range: FfiRefBounds) -> Self {
|
||||||
Self {
|
Self {
|
||||||
ptr,
|
ptr,
|
||||||
dereferenceable,
|
flags,
|
||||||
range,
|
boundary: range,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,14 +40,19 @@ impl FfiRef {
|
||||||
this: LuaAnyUserData<'lua>,
|
this: LuaAnyUserData<'lua>,
|
||||||
) -> LuaResult<LuaAnyUserData<'lua>> {
|
) -> LuaResult<LuaAnyUserData<'lua>> {
|
||||||
let target = this.borrow::<FfiRef>()?;
|
let target = this.borrow::<FfiRef>()?;
|
||||||
|
let mut flags = target.flags.clone();
|
||||||
|
|
||||||
|
// FIXME:
|
||||||
|
// We cannot dereference ref which created by lua, in lua
|
||||||
|
flags.set_dereferenceable(false);
|
||||||
|
|
||||||
let luaref = lua.create_userdata(FfiRef::new(
|
let luaref = lua.create_userdata(FfiRef::new(
|
||||||
ptr::from_ref(&target.ptr) as *mut (),
|
ptr::from_ref(&target.ptr) as *mut (),
|
||||||
true,
|
flags,
|
||||||
Some(FfiRefBounds {
|
FfiRefBounds {
|
||||||
low: 0,
|
below: 0,
|
||||||
high: size_of::<usize>(),
|
above: size_of::<usize>(),
|
||||||
}),
|
},
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
// If the ref holds a box, make sure the new ref also holds the box by holding ref
|
// If the ref holds a box, make sure the new ref also holds the box by holding ref
|
||||||
|
@ -55,26 +65,51 @@ impl FfiRef {
|
||||||
self.ptr
|
self.ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn deref(&self) -> Self {
|
pub unsafe fn deref(&self) -> LuaResult<Self> {
|
||||||
// FIXME
|
self.flags
|
||||||
Self::new(*self.ptr.cast::<*mut ()>(), true, None)
|
.is_dereferenceable()
|
||||||
|
.then_some(())
|
||||||
|
.ok_or(LuaError::external("This pointer is not dereferenceable."))?;
|
||||||
|
|
||||||
|
self.boundary
|
||||||
|
.check_sized(0, size_of::<usize>())
|
||||||
|
.then_some(())
|
||||||
|
.ok_or(LuaError::external(
|
||||||
|
"Offset is out of bounds. Dereferencing pointer requires size of usize",
|
||||||
|
))?;
|
||||||
|
|
||||||
|
// FIXME flags
|
||||||
|
Ok(Self::new(
|
||||||
|
*self.ptr.cast::<*mut ()>(),
|
||||||
|
self.flags.clone(),
|
||||||
|
UNSIZED_BOUNDS,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_nullptr(&self) -> bool {
|
||||||
|
self.ptr as usize == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn offset(&self, offset: isize) -> LuaResult<Self> {
|
pub unsafe fn offset(&self, offset: isize) -> LuaResult<Self> {
|
||||||
if let Some(ref t) = self.range {
|
self.flags
|
||||||
if !t.check(offset) {
|
.is_offsetable()
|
||||||
return Err(LuaError::external(format!(
|
.then_some(())
|
||||||
"Offset is out of bounds. high: {}, low: {}. offset got {}",
|
.ok_or(LuaError::external("This pointer is not offsetable."))?;
|
||||||
t.high, t.low, offset
|
|
||||||
)));
|
// Check boundary, if exceed, return error
|
||||||
}
|
self.boundary.check(offset).then_some(()).ok_or_else(|| {
|
||||||
}
|
LuaError::external(format!(
|
||||||
let range = self.range.as_ref().map(|t| t.offset(offset));
|
"Offset is out of bounds. high: {}, low: {}. offset got {}",
|
||||||
|
self.boundary.above, self.boundary.below, offset
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let boundary = self.boundary.offset(offset);
|
||||||
|
|
||||||
Ok(Self::new(
|
Ok(Self::new(
|
||||||
self.ptr.byte_offset(offset),
|
self.ptr.byte_offset(offset),
|
||||||
self.dereferenceable,
|
self.flags.clone(),
|
||||||
range,
|
boundary,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +119,7 @@ impl LuaUserData for FfiRef {
|
||||||
methods.add_function("deref", |lua, this: LuaAnyUserData| {
|
methods.add_function("deref", |lua, this: LuaAnyUserData| {
|
||||||
let inner = get_association(lua, REF_INNER, &this)?;
|
let inner = get_association(lua, REF_INNER, &this)?;
|
||||||
let ffiref = this.borrow::<FfiRef>()?;
|
let ffiref = this.borrow::<FfiRef>()?;
|
||||||
let result = lua.create_userdata(unsafe { ffiref.deref() })?;
|
let result = lua.create_userdata(unsafe { ffiref.deref()? })?;
|
||||||
|
|
||||||
if let Some(t) = inner {
|
if let Some(t) = inner {
|
||||||
// if let Some(u) = get_association(lua, regname, value) {}
|
// if let Some(u) = get_association(lua, regname, value) {}
|
||||||
|
@ -108,5 +143,18 @@ impl LuaUserData for FfiRef {
|
||||||
let ffiref = FfiRef::luaref(lua, this)?;
|
let ffiref = FfiRef::luaref(lua, this)?;
|
||||||
Ok(ffiref)
|
Ok(ffiref)
|
||||||
});
|
});
|
||||||
|
methods.add_method("isNullptr", |_, this, ()| Ok(this.is_nullptr()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_nullptr(lua: &Lua) -> LuaResult<LuaAnyUserData> {
|
||||||
|
// https://en.cppreference.com/w/cpp/types/nullptr_t
|
||||||
|
lua.create_userdata(FfiRef::new(
|
||||||
|
ptr::null_mut::<()>().cast(),
|
||||||
|
FfiRefFlagList::zero(),
|
||||||
|
// usize::MAX means that nullptr is can be 'any' pointer type
|
||||||
|
// We check size of inner data. give ffi.box(1):ref() as argument which typed as i32:ptr() will fail,
|
||||||
|
// throw lua error
|
||||||
|
UNSIZED_BOUNDS,
|
||||||
|
))
|
||||||
|
}
|
|
@ -1,11 +1,10 @@
|
||||||
pub(super) mod ffi_association;
|
pub mod ffi_association;
|
||||||
pub(super) mod ffi_bounds;
|
pub mod ffi_box;
|
||||||
pub(super) mod ffi_box;
|
pub mod ffi_helper;
|
||||||
pub(super) mod ffi_helper;
|
pub mod ffi_lib;
|
||||||
pub(super) mod ffi_lib;
|
pub mod ffi_native;
|
||||||
pub(super) mod ffi_platform;
|
pub mod ffi_raw;
|
||||||
pub(super) mod ffi_raw;
|
pub mod ffi_ref;
|
||||||
pub(super) mod ffi_ref;
|
|
||||||
|
|
||||||
// Named registry table names
|
// Named registry table names
|
||||||
mod association_names {
|
mod association_names {
|
||||||
|
|
|
@ -3,14 +3,12 @@
|
||||||
use lune_utils::TableBuilder;
|
use lune_utils::TableBuilder;
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
use crate::c::{c_fn::CFn, c_struct::CStruct, create_all_c_types, create_all_types};
|
||||||
|
use crate::ffi::{ffi_box::FfiBox, ffi_lib::FfiLib, ffi_ref::create_nullptr};
|
||||||
|
|
||||||
mod c;
|
mod c;
|
||||||
mod ffi;
|
mod ffi;
|
||||||
|
|
||||||
use crate::c::{c_fn::CFn, c_struct::CStruct, create_all_types};
|
|
||||||
use crate::ffi::{
|
|
||||||
ffi_association::get_table, ffi_box::FfiBox, ffi_lib::FfiLib, ffi_platform::get_platform_value,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Creates the `ffi` standard library module.
|
Creates the `ffi` standard library module.
|
||||||
|
|
||||||
|
@ -19,10 +17,10 @@ use crate::ffi::{
|
||||||
Errors when out of memory.
|
Errors when out of memory.
|
||||||
*/
|
*/
|
||||||
pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
|
pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
|
||||||
let ctypes = create_all_types(lua)?;
|
|
||||||
let result = TableBuilder::new(lua)?
|
let result = TableBuilder::new(lua)?
|
||||||
.with_values(ctypes)?
|
.with_values(create_all_types(lua)?)?
|
||||||
.with_values(get_platform_value())?
|
.with_values(create_all_c_types(lua)?)?
|
||||||
|
.with_value("nullptr", create_nullptr(lua)?)?
|
||||||
.with_function("box", |_, size: usize| Ok(FfiBox::new(size)))?
|
.with_function("box", |_, size: usize| Ok(FfiBox::new(size)))?
|
||||||
// TODO: discuss about function name. matching with io.open is better?
|
// TODO: discuss about function name. matching with io.open is better?
|
||||||
.with_function("dlopen", |_, name: String| {
|
.with_function("dlopen", |_, name: String| {
|
||||||
|
@ -40,7 +38,7 @@ pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
let result = result.with_function("debug_associate", |lua, str: String| {
|
let result = result.with_function("debug_associate", |lua, str: String| {
|
||||||
get_table(lua, str.as_ref())
|
crate::ffi::ffi_association::get_table(lua, str.as_ref())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
result.build_readonly()
|
result.build_readonly()
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
- last thing to do
|
|
||||||
- [ ] Add tests
|
|
||||||
- [ ] Add docs
|
|
||||||
- [ ] Typing
|
|
||||||
|
|
||||||
pragma pack?
|
|
||||||
|
|
||||||
# Raw
|
|
||||||
|
|
||||||
- [ ] Raw:toRef()
|
|
||||||
- [ ] Raw:toBox()
|
|
||||||
- [ ] Raw:intoBox()
|
|
||||||
- [ ] Raw:intoRef()
|
|
||||||
|
|
||||||
# Box
|
|
||||||
|
|
||||||
- [x] ffi.box(size)
|
|
||||||
- [x] .size
|
|
||||||
- [x] :zero()
|
|
||||||
- [x] :ref(offset?=0) => ref
|
|
||||||
- [x] tostring
|
|
||||||
|
|
||||||
- [~] :copy(box,size?=-1,offset?=0)
|
|
||||||
- working on it
|
|
||||||
|
|
||||||
# Ref (Unsafe)
|
|
||||||
|
|
||||||
- [ ] high, low Boundaries
|
|
||||||
- [ ] iter
|
|
||||||
|
|
||||||
- [x] ref:deref() -> ref
|
|
||||||
- [x] ref:offset(bytes) -> ref
|
|
||||||
- [x] ref:ref() -> ref
|
|
||||||
|
|
||||||
~~- [ ] ref:fromRef(size,offset?=0) ?? what is this~~
|
|
||||||
~~- [ ] ref:fromBox(size,offset?=0) ?? what is this~~
|
|
||||||
|
|
||||||
# Struct
|
|
||||||
|
|
||||||
- [x] :offset(index)
|
|
||||||
- [x] :ptr()
|
|
||||||
- [x] .inner[n]
|
|
||||||
- [!] .size
|
|
||||||
- [ ] #
|
|
||||||
- [x] tostring
|
|
||||||
|
|
||||||
size, offset is strange. maybe related to cif state.
|
|
||||||
|
|
||||||
# Type
|
|
||||||
|
|
||||||
- [ ] :toBox(luavalue)
|
|
||||||
|
|
||||||
Very stupid idea.
|
|
||||||
from(box|ref|raw, offset) is better idea i think.
|
|
||||||
|
|
||||||
- [ ] :fromBox(box,offset?=0)
|
|
||||||
- [ ] :intoBox(luavalue,box,offset?=0)
|
|
||||||
- [ ] :fromRef(ref,offset?=0)
|
|
||||||
- [ ] :intoRef(luavalue,ref,offset?=0)
|
|
||||||
- [ ] :fromRaw(raw,offset?=0)
|
|
||||||
|
|
||||||
- [ ] :castBox(box,type) TODO
|
|
||||||
- [ ]
|
|
||||||
|
|
||||||
- [ ] :sum
|
|
||||||
- [ ] :mul
|
|
||||||
- [ ] :sub
|
|
||||||
|
|
||||||
## subtype
|
|
||||||
|
|
||||||
- [x] :ptr() -> Ptr
|
|
||||||
- [~] :arr(len) -> Arr
|
|
||||||
- [x] .size
|
|
||||||
|
|
||||||
# Ptr
|
|
||||||
|
|
||||||
- [x] .inner
|
|
||||||
- [x] .size
|
|
||||||
- [x] :ptr()
|
|
||||||
- [~] :arr()
|
|
||||||
|
|
||||||
## Arr
|
|
||||||
|
|
||||||
## Void
|
|
||||||
|
|
||||||
`ffi.void`
|
|
||||||
|
|
||||||
Zero sized type.
|
|
||||||
|
|
||||||
## Fn
|
|
||||||
|
|
||||||
Prototype type of some function. converts lua function into native function pointer or native function pointer into lua function.
|
|
||||||
|
|
||||||
`ffi.fn({ type }, type) -> fn`
|
|
||||||
|
|
||||||
:toLua( ref ) -> luafunction
|
|
||||||
:toBox( luafunction ) -> ref
|
|
||||||
|
|
||||||
> TODO: rust, and another ABI support
|
|
Loading…
Add table
Reference in a new issue