mirror of
https://github.com/lune-org/lune.git
synced 2025-04-03 01:50:55 +01:00
Add Data:copyFrom, tests and annotation (#243)
This commit is contained in:
parent
34a5b39277
commit
154c68a64e
12 changed files with 514 additions and 35 deletions
2
.gitattributes
vendored
2
.gitattributes
vendored
|
@ -7,6 +7,6 @@
|
|||
# Ensure all txt files within tests use LF
|
||||
tests/**/*.txt eol=lf
|
||||
|
||||
# Remove test c, typescript from language list
|
||||
# Remove test c and typescript from language list
|
||||
tests/ffi/**/*.c linguist-vendored
|
||||
tests/ffi/**/*.ts linguist-vendored
|
||||
|
|
|
@ -6,6 +6,10 @@ See [tests/ffi](../../tests/ffi/README.md)
|
|||
|
||||
## TODO
|
||||
|
||||
- Deref
|
||||
|
||||
- Big endianness / Little endianness variable (On process.endianness)
|
||||
|
||||
- CString
|
||||
|
||||
- Add buffer for owned data support
|
||||
|
@ -25,6 +29,8 @@ See [tests/ffi](../../tests/ffi/README.md)
|
|||
|
||||
- Add varargs support
|
||||
|
||||
- Array argument in cfn
|
||||
|
||||
## Code structure
|
||||
|
||||
### /c
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
use std::{alloc, alloc::Layout, boxed::Box, mem::ManuallyDrop, ptr};
|
||||
use std::{
|
||||
alloc::{self, Layout},
|
||||
boxed::Box,
|
||||
mem::ManuallyDrop,
|
||||
ptr,
|
||||
};
|
||||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use super::helper::method_provider;
|
||||
use crate::{
|
||||
data::{association_names::REF_INNER, RefBounds, RefData, RefFlag},
|
||||
ffi::{association, bit_mask::*, FfiData},
|
||||
|
@ -148,6 +154,7 @@ impl LuaUserData for BoxData {
|
|||
fields.add_field_method_get("size", |_, this| Ok(this.size()));
|
||||
}
|
||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
method_provider::provide_copy_from(methods);
|
||||
// For convenience, :zero returns self.
|
||||
methods.add_function_mut("zero", |_, this: LuaAnyUserData| {
|
||||
this.borrow_mut::<BoxData>()?.zero();
|
||||
|
|
41
crates/lune-std-ffi/src/data/helper.rs
Normal file
41
crates/lune-std-ffi/src/data/helper.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
use mlua::prelude::*;
|
||||
|
||||
use super::{FfiData, GetFfiData};
|
||||
|
||||
pub mod method_provider {
|
||||
|
||||
use super::*;
|
||||
|
||||
pub fn provide_copy_from<'lua, Target, M>(methods: &mut M)
|
||||
where
|
||||
Target: FfiData,
|
||||
M: LuaUserDataMethods<'lua, Target>,
|
||||
{
|
||||
methods.add_method(
|
||||
"copyFrom",
|
||||
|_lua,
|
||||
this,
|
||||
(src, length, dst_offset, src_offset): (
|
||||
LuaAnyUserData,
|
||||
usize,
|
||||
Option<isize>,
|
||||
Option<isize>,
|
||||
)| unsafe {
|
||||
let dst_offset = dst_offset.unwrap_or(0);
|
||||
let src_offset = src_offset.unwrap_or(0);
|
||||
let src = src.get_ffi_data()?;
|
||||
|
||||
if !src.check_inner_boundary(src_offset, length) {
|
||||
return Err(LuaError::external("Source boundary check failed"));
|
||||
}
|
||||
if !this.check_inner_boundary(dst_offset, length) {
|
||||
return Err(LuaError::external("Self boundary check failed"));
|
||||
}
|
||||
|
||||
this.copy_from(&src, length, dst_offset, src_offset);
|
||||
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ use mlua::prelude::*;
|
|||
mod box_data;
|
||||
mod callable_data;
|
||||
mod closure_data;
|
||||
mod helper;
|
||||
mod lib_data;
|
||||
mod ref_data;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::{mem::ManuallyDrop, ptr};
|
|||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use super::helper::method_provider;
|
||||
use crate::{
|
||||
data::association_names::REF_INNER,
|
||||
ffi::{association, bit_mask::*, FfiData},
|
||||
|
@ -91,6 +92,10 @@ impl RefData {
|
|||
(**self.ptr) as usize == 0
|
||||
}
|
||||
|
||||
pub fn leak(&mut self) {
|
||||
self.flags = u8_set(self.flags, RefFlag::Leaked.value(), true);
|
||||
}
|
||||
|
||||
pub unsafe fn offset(&self, offset: isize) -> LuaResult<Self> {
|
||||
u8_test(self.flags, RefFlag::Offsetable.value())
|
||||
.then_some(())
|
||||
|
@ -147,6 +152,8 @@ impl FfiData for RefData {
|
|||
|
||||
impl LuaUserData for RefData {
|
||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
method_provider::provide_copy_from(methods);
|
||||
|
||||
// FIXME:
|
||||
methods.add_function("deref", |lua, this: LuaAnyUserData| {
|
||||
let inner = association::get(lua, REF_INNER, &this)?;
|
||||
|
@ -171,10 +178,12 @@ impl LuaUserData for RefData {
|
|||
|
||||
Ok(userdata)
|
||||
});
|
||||
// FIXME:
|
||||
methods.add_function_mut("leak", |lua, this: LuaAnyUserData| {
|
||||
this.borrow_mut::<RefData>()?.leak();
|
||||
RefData::luaref(lua, this)
|
||||
});
|
||||
methods.add_function("ref", |lua, this: LuaAnyUserData| {
|
||||
let ffiref = RefData::luaref(lua, this)?;
|
||||
Ok(ffiref)
|
||||
RefData::luaref(lua, this)
|
||||
});
|
||||
methods.add_method("isNull", |_, this, ()| Ok(this.is_nullptr()));
|
||||
}
|
||||
|
|
|
@ -62,6 +62,17 @@ pub trait FfiData {
|
|||
unsafe fn get_inner_pointer(&self) -> *mut ();
|
||||
fn is_writable(&self) -> bool;
|
||||
fn is_readable(&self) -> bool;
|
||||
unsafe fn copy_from(
|
||||
&self,
|
||||
src: &Ref<dyn FfiData>,
|
||||
length: usize,
|
||||
dst_offset: isize,
|
||||
src_offset: isize,
|
||||
) {
|
||||
self.get_inner_pointer()
|
||||
.byte_offset(dst_offset)
|
||||
.copy_from(src.get_inner_pointer().byte_offset(src_offset), length);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FfiArg {
|
||||
|
|
53
tests/ffi/read_boundary.luau
Normal file
53
tests/ffi/read_boundary.luau
Normal file
|
@ -0,0 +1,53 @@
|
|||
local ffi = require("@lune/ffi")
|
||||
|
||||
local ok
|
||||
|
||||
-- Case1: Success
|
||||
ok = pcall(function()
|
||||
local box = ffi.u8:box(1)
|
||||
ffi.u8:readData(box)
|
||||
end)
|
||||
assert(ok, "assersion failed, Case1 should success")
|
||||
|
||||
-- Case2: Fail
|
||||
ok = pcall(function()
|
||||
local box = ffi.u8:box(1)
|
||||
ffi.u16:readData(box)
|
||||
end)
|
||||
assert(not ok, "assersion failed, Case2 should fail")
|
||||
|
||||
-- Case3: Success
|
||||
ok = pcall(function()
|
||||
local box = ffi.box(ffi.u8.size * 2)
|
||||
ffi.u16:readData(box)
|
||||
end)
|
||||
assert(ok, "assersion failed, Case3 should success")
|
||||
|
||||
-- Case4: Success
|
||||
|
||||
ok = pcall(function()
|
||||
local box = ffi.box(ffi.u8.size * 2)
|
||||
ffi.u8:readData(box, ffi.u8.size)
|
||||
end)
|
||||
assert(ok, "assersion failed, Case4 should success")
|
||||
|
||||
-- Case5: Fail
|
||||
ok = pcall(function()
|
||||
local box = ffi.u8:box(1):ref()
|
||||
ffi.u16:readData(box)
|
||||
end)
|
||||
assert(not ok, "assersion failed, Case5 should fail")
|
||||
|
||||
-- Case6: Success
|
||||
ok = pcall(function()
|
||||
local box = ffi.box(ffi.u8.size * 2):ref()
|
||||
ffi.u16:readData(box)
|
||||
end)
|
||||
assert(ok, "assersion failed, Case6 should success")
|
||||
|
||||
-- Case7: Fail
|
||||
ok = pcall(function()
|
||||
local box = ffi.box(ffi.u8.size * 2):ref(ffi.u16.size)
|
||||
ffi.u16:readData(box)
|
||||
end)
|
||||
assert(ok, "assersion failed, Case7 should fail")
|
46
tests/ffi/write_boundary.luau
Normal file
46
tests/ffi/write_boundary.luau
Normal file
|
@ -0,0 +1,46 @@
|
|||
local ffi = require("@lune/ffi")
|
||||
local c = ffi.c
|
||||
|
||||
local ok
|
||||
|
||||
-- Case1: Fail
|
||||
ok = pcall(function()
|
||||
local box = ffi.box(c.int.size - 1)
|
||||
c.int:writeData(box, 10)
|
||||
end)
|
||||
assert(not ok, "assersion failed, Case1 should fail")
|
||||
|
||||
-- Case2: Success
|
||||
ok = pcall(function()
|
||||
local box = ffi.box(c.int.size)
|
||||
c.int:writeData(box, 10)
|
||||
end)
|
||||
assert(ok, "assersion failed, Case2 should success")
|
||||
|
||||
-- Case3: Success
|
||||
ok = pcall(function()
|
||||
local box = ffi.box(c.int.size * 2)
|
||||
c.int:writeData(box, 10, c.int.size)
|
||||
end)
|
||||
assert(ok, "assersion failed, Case3 should success")
|
||||
|
||||
-- Case4: Fail
|
||||
ok = pcall(function()
|
||||
local box = ffi.box(c.int.size * 2)
|
||||
c.int:writeData(box, 10, c.int.size * 2)
|
||||
end)
|
||||
assert(not ok, "assersion failed, Case4 should fail")
|
||||
|
||||
-- Case5: Success
|
||||
ok = pcall(function()
|
||||
local box = ffi.box(c.int.size * 2):ref()
|
||||
c.int:writeData(box, 10, c.int.size)
|
||||
end)
|
||||
assert(ok, "assersion failed, Case5 should success")
|
||||
|
||||
-- Case6: Fail
|
||||
ok = pcall(function()
|
||||
local box = ffi.box(c.int.size * 2):ref()
|
||||
c.int:writeData(box, 10, c.int.size * 2)
|
||||
end)
|
||||
assert(not ok, "assersion failed, Case6 should fail")
|
365
types/ffi.luau
365
types/ffi.luau
|
@ -1,11 +1,41 @@
|
|||
--[=[
|
||||
@class FFI
|
||||
|
||||
Built-in library for foreign function interface
|
||||
Built-in library for foreign function interface.
|
||||
|
||||
### Example usage
|
||||
|
||||
lib.c:
|
||||
```c
|
||||
int add(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
```
|
||||
init.luau:
|
||||
```lua
|
||||
local ffi = require("@lune/ffi")
|
||||
|
||||
-- Create function signature
|
||||
local addSignature = ffi.c.fn({ ffi.c.int, ffi.c.int }, ffi.c.int)
|
||||
|
||||
-- Load library
|
||||
local lib = ffi.open("./lib.so")
|
||||
|
||||
-- Get symbol from library
|
||||
local addSymbol = lib:find("add")
|
||||
|
||||
-- Create CallableData
|
||||
local add = addSignature:callable(addSymbol)
|
||||
|
||||
-- Create result box and arguments
|
||||
local result = ffi.box(ffi.c.int.size)
|
||||
local a = ffi.c.int:box(1)
|
||||
local b = ffi.c.int:box(2)
|
||||
|
||||
-- Call external function
|
||||
add(result, a:ref(), b:ref())
|
||||
|
||||
-- Get number from result
|
||||
print(ffi.c.int:readData(result))
|
||||
```
|
||||
]=]
|
||||
local ffi = {}
|
||||
|
@ -24,19 +54,83 @@ ffi.c = c
|
|||
--[=[
|
||||
@class RefData
|
||||
|
||||
A user manageable memory reference
|
||||
A user manageable memory reference.
|
||||
]=]
|
||||
export type RefData = {
|
||||
--[=[
|
||||
@within RefData
|
||||
@tag Method
|
||||
@method deref
|
||||
|
||||
Get a RefData by dereference this reference.
|
||||
|
||||
@return A dereferenced `RefData`
|
||||
]=]
|
||||
deref: (self: RefData) -> RefData,
|
||||
--[=[
|
||||
@within RefData
|
||||
@tag Method
|
||||
@method offset
|
||||
|
||||
Create a reference with specific offset from this reference.
|
||||
|
||||
@param offset Create a reference at the given offset
|
||||
@return A offseted reference
|
||||
]=]
|
||||
offset: (self: RefData, offset: number) -> RefData,
|
||||
--[=[
|
||||
@within RefData
|
||||
@tag Method
|
||||
@method ref
|
||||
|
||||
Create a reference of this reference.
|
||||
|
||||
The created reference keeps the box from being garbage collected until the reference itself is collected.
|
||||
|
||||
@return A reference of this reference
|
||||
]=]
|
||||
ref: (self: RefData) -> RefData,
|
||||
--[=[
|
||||
@within RefData
|
||||
@tag Method
|
||||
@method leak
|
||||
|
||||
Create a reference of this reference after leaking it.
|
||||
|
||||
GC doesn't manage destruction after this action. You must free it later.
|
||||
|
||||
@return A reference of this reference
|
||||
]=]
|
||||
leak: (self: RefData) -> RefData,
|
||||
--[=[
|
||||
@within RefData
|
||||
@tag Method
|
||||
@method isNull
|
||||
|
||||
Check reference is null or not.
|
||||
|
||||
@return Whether reference is null or not
|
||||
]=]
|
||||
isNull: (self: RefData) -> boolean,
|
||||
--[=[
|
||||
@within RefData
|
||||
@tag Method
|
||||
@method copyFrom
|
||||
|
||||
Copy content from another data.
|
||||
|
||||
@param src The source data
|
||||
@param len The amount of data to copy, in bytes
|
||||
@param dst_offset The offset in the destination where the data will be pasted
|
||||
@param src_offset The offset in the source data from where the data will be copied
|
||||
]=]
|
||||
copyFrom: (self: RefData, src: (BoxData|RefData), length: number, dst_offset: number, src_offset: number)->();
|
||||
}
|
||||
|
||||
--[=[
|
||||
@class BoxData
|
||||
|
||||
A user manageable heap memory
|
||||
A user manageable heap memory.
|
||||
]=]
|
||||
export type BoxData = {
|
||||
--[=[
|
||||
|
@ -44,7 +138,7 @@ export type BoxData = {
|
|||
@tag Field
|
||||
@field size
|
||||
|
||||
Size of the box.
|
||||
The size of the box.
|
||||
]=]
|
||||
size: number,
|
||||
|
||||
|
@ -65,8 +159,9 @@ export type BoxData = {
|
|||
|
||||
Create a reference of the box after leaking it.
|
||||
|
||||
GC doesn't manage destruction after this action. You must free it later
|
||||
GC doesn't manage destruction after this action. You must free it later.
|
||||
|
||||
@param offset Create a reference at the given offset
|
||||
@return A reference of the box
|
||||
]=]
|
||||
leak: (self: BoxData, offset: number?) -> RefData,
|
||||
|
@ -77,15 +172,31 @@ export type BoxData = {
|
|||
|
||||
Create a reference of the box.
|
||||
|
||||
The created reference keeps the box from being garbage collected until the reference itself is collected.
|
||||
|
||||
@param offset Create a reference at the given offset
|
||||
@return A reference of the box
|
||||
]=]
|
||||
ref: (self: BoxData, offset: number?) -> RefData,
|
||||
--[=[
|
||||
@within BoxData
|
||||
@tag Method
|
||||
@method copyFrom
|
||||
|
||||
Copy content from another data.
|
||||
|
||||
@param src The source data
|
||||
@param len The amount of data to copy, in bytes
|
||||
@param dst_offset The offset in the destination where the data will be pasted
|
||||
@param src_offset The offset in the source data from where the data will be copied
|
||||
]=]
|
||||
copyFrom: (self: BoxData, src: (BoxData|RefData), length: number, dst_offset: number, src_offset: number)->();
|
||||
}
|
||||
|
||||
--[=[
|
||||
@class LibData
|
||||
|
||||
A dynamic opened library handle
|
||||
|
||||
A dynamic opened library handle.
|
||||
]=]
|
||||
export type LibData = {
|
||||
--[=[
|
||||
|
@ -105,9 +216,12 @@ export type LibData = {
|
|||
|
||||
--[=[
|
||||
@class CallableData
|
||||
@tag unsafe
|
||||
|
||||
A callable external function
|
||||
A callable external function.
|
||||
|
||||
To call external function, you should provide memory for the return value and references for the arguments.
|
||||
|
||||
If return type is `void`, pass `nil`.
|
||||
]=]
|
||||
export type CallableData = (ret: (RefData|BoxData)?, ...RefData)->() & {
|
||||
-- apply: (self: Callable, args: Args)->AppliedCallable,
|
||||
|
@ -116,7 +230,9 @@ export type CallableData = (ret: (RefData|BoxData)?, ...RefData)->() & {
|
|||
--[=[
|
||||
@class ClosureData
|
||||
|
||||
A lua function wrapper for function pointer
|
||||
A lua function wrapper for the function pointer.
|
||||
|
||||
To return some data, write value into ret reference.
|
||||
]=]
|
||||
export type ClosureData = {
|
||||
--[=[
|
||||
|
@ -124,7 +240,9 @@ export type ClosureData = {
|
|||
@tag Method
|
||||
@method ref
|
||||
|
||||
Create a reference of the closure. usually can be used for passing function pointer as argument
|
||||
Create a reference of the closure. usually can be used for passing function pointer as argument.
|
||||
|
||||
The created reference keeps the closure from being garbage collected until the reference itself is collected.
|
||||
|
||||
@return A reference of the closure
|
||||
]=]
|
||||
|
@ -137,7 +255,21 @@ export type ClosureData = {
|
|||
|
||||
-- NOTE: T is a unique identifier for the `CType` and R is the closest Lua type.
|
||||
export type CTypeInfo<T, R> = {
|
||||
--[=[
|
||||
@within CTypeInfo
|
||||
@tag Field
|
||||
@field size
|
||||
|
||||
The size of the type in bytes.
|
||||
]=]
|
||||
size: number,
|
||||
--[=[
|
||||
@within CTypeInfo
|
||||
@tag Field
|
||||
@field signedness
|
||||
|
||||
The signedness of the type.
|
||||
]=]
|
||||
signedness: boolean,
|
||||
|
||||
-- subtype
|
||||
|
@ -156,7 +288,23 @@ export type CTypeInfo<T, R> = {
|
|||
type NumCType<T> = CTypeInfo<T, (number|any)>
|
||||
|
||||
export type CPtrInfo<T> = {
|
||||
--[=[
|
||||
@within CPtrInfo
|
||||
@tag Field
|
||||
@field size
|
||||
|
||||
The size of a pointer. should be the same for all pointers.
|
||||
|
||||
Equivalent to `ffi.c.usize.size`.
|
||||
]=]
|
||||
size: number,
|
||||
--[=[
|
||||
@within CPtrInfo
|
||||
@tag Field
|
||||
@field inner
|
||||
|
||||
The inner type of the pointer.
|
||||
]=]
|
||||
inner: T,
|
||||
|
||||
-- subtype
|
||||
|
@ -169,9 +317,35 @@ export type CPtrInfo<T> = {
|
|||
writeRef: (self: CPtrInfo<T>, target: (RefData|BoxData), value: (RefData|BoxData), offset: number?) -> (),
|
||||
}
|
||||
|
||||
--[=[
|
||||
@class CArrInfo
|
||||
|
||||
A c sized array type information.
|
||||
]=]
|
||||
export type CArrInfo<T, R> = {
|
||||
--[=[
|
||||
@within CArrInfo
|
||||
@tag Field
|
||||
@field size
|
||||
|
||||
The total size of the array in bytes.
|
||||
]=]
|
||||
size: number,
|
||||
--[=[
|
||||
@within CArrInfo
|
||||
@tag Field
|
||||
@field length
|
||||
|
||||
The length of the array.
|
||||
]=]
|
||||
length: number,
|
||||
--[=[
|
||||
@within CArrInfo
|
||||
@tag Field
|
||||
@field inner
|
||||
|
||||
The inner element type of the array.
|
||||
]=]
|
||||
inner: T,
|
||||
|
||||
-- subtype
|
||||
|
@ -186,15 +360,62 @@ export type CArrInfo<T, R> = {
|
|||
offset: (self: CArrInfo<T, R>, index: number) -> number,
|
||||
}
|
||||
|
||||
--[=[
|
||||
@class CFnInfo
|
||||
|
||||
A c function signature type information.
|
||||
]=]
|
||||
export type CFnInfo = {
|
||||
--[=[
|
||||
@within CFnInfo
|
||||
@tag Method
|
||||
@method callable
|
||||
|
||||
Create a callable from reference.
|
||||
|
||||
@return Struct array type
|
||||
]=]
|
||||
callable: (self: CFnInfo, functionRef: RefData) -> CallableData,
|
||||
--[=[
|
||||
@within CFnInfo
|
||||
@tag Method
|
||||
@method closure
|
||||
|
||||
Create a closure from lua function.
|
||||
|
||||
@return A closure.
|
||||
]=]
|
||||
closure: (self: CFnInfo, (ret: RefData, ...RefData)->()) -> ClosureData,
|
||||
}
|
||||
|
||||
--[=[
|
||||
@class CStructInfo
|
||||
|
||||
A c struct type information.
|
||||
]=]
|
||||
export type CStructInfo = {
|
||||
size: number,
|
||||
|
||||
--[=[
|
||||
@within CSturctInfo
|
||||
@tag Method
|
||||
@method arr
|
||||
|
||||
Create a struct array type.
|
||||
|
||||
@param len The length of the array
|
||||
@return A struct array type
|
||||
]=]
|
||||
arr: (self: CStructInfo, len: number) -> CArrInfo<CStructInfo, {any}>,
|
||||
--[=[
|
||||
@within CSturctInfo
|
||||
@tag Method
|
||||
@method ptr
|
||||
|
||||
Create a struct pointer type.
|
||||
|
||||
@return A struct pointer type
|
||||
]=]
|
||||
ptr: (self: CStructInfo) -> CPtrInfo<CStructInfo>,
|
||||
|
||||
box: (self: CStructInfo, table: { any }) -> BoxData,
|
||||
|
@ -217,9 +438,9 @@ export type CVoidInfo = {
|
|||
@tag Method
|
||||
@method ptr
|
||||
|
||||
Create a generic pointer type
|
||||
Create a generic pointer type.
|
||||
|
||||
@return Generic pointer type
|
||||
@return Generic pointer type, equivalent to `*void` in C.
|
||||
]=]
|
||||
ptr: (self: CVoidInfo) -> CPtrInfo<CVoidInfo>,
|
||||
}
|
||||
|
@ -233,7 +454,7 @@ c.void = {} :: CVoidInfo
|
|||
@class u8
|
||||
@within FFI
|
||||
|
||||
A 8-bit sized unsigned integer, Equivalent to `uint8_t` in `stdint`
|
||||
A 8-bit sized unsigned integer, Equivalent to `uint8_t` in `stdint`.
|
||||
]=]
|
||||
ffi.u8 = {} :: u8
|
||||
export type u8 = NumCType<"u8">
|
||||
|
@ -241,7 +462,7 @@ export type u8 = NumCType<"u8">
|
|||
@class u16
|
||||
@within FFI
|
||||
|
||||
A 16-bit sized unsigned integer, Equivalent to `uint16_t` in `stdint`
|
||||
A 16-bit sized unsigned integer, Equivalent to `uint16_t` in `stdint`.
|
||||
]=]
|
||||
ffi.u16 = {} :: u16
|
||||
export type u16 = NumCType<"u16">
|
||||
|
@ -249,7 +470,7 @@ export type u16 = NumCType<"u16">
|
|||
@class u32
|
||||
@within FFI
|
||||
|
||||
A 32-bit sized unsigned integer, Equivalent to `uint32_t` in `stdint`
|
||||
A 32-bit sized unsigned integer, Equivalent to `uint32_t` in `stdint`.
|
||||
]=]
|
||||
ffi.u32 = {} :: u32
|
||||
export type u32 = NumCType<"u32">
|
||||
|
@ -257,7 +478,7 @@ export type u32 = NumCType<"u32">
|
|||
@class u64
|
||||
@within FFI
|
||||
|
||||
A 64-bit sized unsigned integer, Equivalent to `uint64_t` in `stdint`
|
||||
A 64-bit sized unsigned integer, Equivalent to `uint64_t` in `stdint`.
|
||||
]=]
|
||||
ffi.u64 = {} :: u64
|
||||
export type u64 = NumCType<"u64">
|
||||
|
@ -265,7 +486,7 @@ export type u64 = NumCType<"u64">
|
|||
@class u128
|
||||
@within FFI
|
||||
|
||||
A 128-bit sized unsigned integer, Equivalent to `uint128_t` in `stdint`
|
||||
A 128-bit sized unsigned integer, Equivalent to `uint128_t` in `stdint`.
|
||||
]=]
|
||||
ffi.u128 = {} :: u128
|
||||
export type u128 = NumCType<"u128">
|
||||
|
@ -273,7 +494,7 @@ export type u128 = NumCType<"u128">
|
|||
@class i8
|
||||
@within FFI
|
||||
|
||||
A 8-bit sized signed integer, Equivalent to `int8_t` in `stdint`
|
||||
A 8-bit sized signed integer, Equivalent to `int8_t` in `stdint`.
|
||||
]=]
|
||||
ffi.i8 = {} :: i8
|
||||
export type i8 = NumCType<"i8">
|
||||
|
@ -281,7 +502,7 @@ export type i8 = NumCType<"i8">
|
|||
@class i16
|
||||
@within FFI
|
||||
|
||||
A 16-bit sized signed integer, Equivalent to `int16_t` in `stdint`
|
||||
A 16-bit sized signed integer, Equivalent to `int16_t` in `stdint`.
|
||||
]=]
|
||||
ffi.i16 = {} :: i16
|
||||
export type i16 = NumCType<"i16">
|
||||
|
@ -289,7 +510,7 @@ export type i16 = NumCType<"i16">
|
|||
@class i32
|
||||
@within FFI
|
||||
|
||||
A 32-bit sized signed integer, Equivalent to `int32_t` in `stdint`
|
||||
A 32-bit sized signed integer, Equivalent to `int32_t` in `stdint`.
|
||||
]=]
|
||||
ffi.i32 = {} :: i32
|
||||
export type i32 = NumCType<"i32">
|
||||
|
@ -297,7 +518,7 @@ export type i32 = NumCType<"i32">
|
|||
@class i64
|
||||
@within FFI
|
||||
|
||||
A 64-bit sized signed integer, Equivalent to `int64_t` in `stdint`
|
||||
A 64-bit sized signed integer, Equivalent to `int64_t` in `stdint`.
|
||||
]=]
|
||||
ffi.i64 = {} :: i64
|
||||
export type i64 = NumCType<"i64">
|
||||
|
@ -305,7 +526,7 @@ export type i64 = NumCType<"i64">
|
|||
@class i128
|
||||
@within FFI
|
||||
|
||||
A 128-bit sized signed integer, Equivalent to `int128_t` in `stdint`
|
||||
A 128-bit sized signed integer, Equivalent to `int128_t` in `stdint`.
|
||||
]=]
|
||||
ffi.i128 = {} :: i128
|
||||
export type i128 = NumCType<"i128">
|
||||
|
@ -313,7 +534,7 @@ export type i128 = NumCType<"i128">
|
|||
@class f32
|
||||
@within FFI
|
||||
|
||||
A single-precision 32-bit sized floating-point, Almost always equivalent to `float` in C
|
||||
A single-precision 32-bit sized floating-point, Almost always equivalent to `float` in C.
|
||||
]=]
|
||||
ffi.f32 = {} :: f32
|
||||
export type f32 = NumCType<"f32">
|
||||
|
@ -321,7 +542,7 @@ export type f32 = NumCType<"f32">
|
|||
@class f64
|
||||
@within FFI
|
||||
|
||||
A double-precision 64-bit sized floating-point, Almost always equivalent to `double` in C
|
||||
A double-precision 64-bit sized floating-point, Almost always equivalent to `double` in C.
|
||||
]=]
|
||||
ffi.f64 = {} :: f64
|
||||
export type f64 = NumCType<"f64">
|
||||
|
@ -329,7 +550,7 @@ export type f64 = NumCType<"f64">
|
|||
@class usize
|
||||
@within FFI
|
||||
|
||||
A machine specific pointer sized unsigned integer,
|
||||
A machine specific pointer sized unsigned integer.
|
||||
]=]
|
||||
ffi.usize = {} :: usize
|
||||
export type usize = NumCType<"usize">
|
||||
|
@ -337,7 +558,7 @@ export type usize = NumCType<"usize">
|
|||
@class isize
|
||||
@within FFI
|
||||
|
||||
A machine specific pointer sized signed integer,
|
||||
A machine specific pointer sized signed integer.
|
||||
]=]
|
||||
ffi.isize = {} :: isize
|
||||
export type isize = NumCType<"isize">
|
||||
|
@ -345,36 +566,120 @@ export type isize = NumCType<"isize">
|
|||
--#endregion Fixed size Rust-style types --
|
||||
|
||||
--#region Variable size C-style types --
|
||||
--[=[
|
||||
@class char
|
||||
@within C
|
||||
|
||||
Compiler defined C `char` type.
|
||||
|
||||
The signedness may differ depending on the compiler and platform.
|
||||
|
||||
You can get signedness by `signedness` field.
|
||||
]=]
|
||||
c.char = {} :: char
|
||||
export type char = NumCType<"char">
|
||||
-- c.float = {} :: float
|
||||
-- export type float = NumCType<"float">
|
||||
-- c.double = {} :: double
|
||||
-- export type double = NumCType<"double">
|
||||
--[=[
|
||||
@class uchar
|
||||
@within C
|
||||
|
||||
Compiler defined C `unsigned char` type.
|
||||
|
||||
Mostly equivalent to `u8`.
|
||||
]=]
|
||||
c.uchar = {} :: uchar
|
||||
export type uchar = NumCType<"uchar">
|
||||
--[=[
|
||||
@class schar
|
||||
@within C
|
||||
|
||||
Compiler defined C `signed char` type.
|
||||
]=]
|
||||
c.schar = {} :: schar
|
||||
export type schar = NumCType<"schar">
|
||||
--[=[
|
||||
@class short
|
||||
@within C
|
||||
|
||||
Compiler defined C `short` type.
|
||||
]=]
|
||||
c.short = {} :: short
|
||||
export type short = NumCType<"short">
|
||||
--[=[
|
||||
@class ushort
|
||||
@within C
|
||||
|
||||
Compiler defined C `unsigned short` type.
|
||||
]=]
|
||||
c.ushort = {} :: ushort
|
||||
export type ushort = NumCType<"ushort">
|
||||
--[=[
|
||||
@class int
|
||||
@within C
|
||||
|
||||
Compiler defined C `int` type.
|
||||
|
||||
The side may differ depending on the compiler and platform.
|
||||
]=]
|
||||
c.int = {} :: int
|
||||
export type int = NumCType<"int">
|
||||
--[=[
|
||||
@class uint
|
||||
@within C
|
||||
|
||||
Compiler defined C `unsigned int` type.
|
||||
|
||||
The side may differ depending on the compiler and platform.
|
||||
]=]
|
||||
c.uint = {} :: uint
|
||||
export type uint = NumCType<"uint">
|
||||
--[=[
|
||||
@class long
|
||||
@within C
|
||||
|
||||
Compiler defined C `long` type.
|
||||
|
||||
The side may differ depending on the compiler and platform.
|
||||
]=]
|
||||
c.long = {} :: long
|
||||
export type long = NumCType<"long">
|
||||
--[=[
|
||||
@class ulong
|
||||
@within C
|
||||
|
||||
Compiler defined C `unsigned long` type.
|
||||
|
||||
The side may differ depending on the compiler and platform.
|
||||
]=]
|
||||
c.ulong = {} :: ulong
|
||||
export type ulong = NumCType<"ulong">
|
||||
--[=[
|
||||
@class longlong
|
||||
@within C
|
||||
|
||||
Compiler defined C `unsigned longlong` type.
|
||||
]=]
|
||||
c.longlong = {} :: longlong
|
||||
export type longlong = NumCType<"longlong">
|
||||
--[=[
|
||||
@class longlong
|
||||
@within C
|
||||
|
||||
Compiler defined C `unsigned longlong` type.
|
||||
]=]
|
||||
c.ulonglong = {} :: ulonglong
|
||||
export type ulonglong = NumCType<"ulonglong">
|
||||
|
||||
--#endregion Variable size C-style types --
|
||||
|
||||
--[=[
|
||||
@class CTypes
|
||||
|
||||
All possible C types.
|
||||
]=]
|
||||
export type CTypes =
|
||||
| u8
|
||||
| u16
|
||||
|
@ -427,7 +732,7 @@ end
|
|||
|
||||
Create a struct type information.
|
||||
|
||||
@param fields An array of CTypes represents the fields of the struct
|
||||
@param fields An array of CTypes represents the fields of the struct
|
||||
@return A struct type information
|
||||
]=]
|
||||
function c.struct(fields: { CTypes }): CStructInfo
|
||||
|
@ -474,7 +779,7 @@ end
|
|||
--[=[
|
||||
@within FFI
|
||||
|
||||
Return `true` if the second argument is an integer (i32)
|
||||
Return `true` if the second argument is an integer (i32).
|
||||
|
||||
@param val A lua value to check
|
||||
@return Whether val is an integer or not
|
||||
|
|
Loading…
Add table
Reference in a new issue