Restruct tests/ffi and add std-ffi tests (#243)

This commit is contained in:
qwreey 2024-10-24 08:34:35 +00:00
parent 00319f03e3
commit 90c0987754
No known key found for this signature in database
GPG key ID: D28DB79297A214BD
35 changed files with 350 additions and 302 deletions

View file

@ -43,7 +43,6 @@ impl FfiSignedness for CFnInfo {
false false
} }
} }
impl FfiSize for CFnInfo { impl FfiSize for CFnInfo {
fn get_size(&self) -> usize { fn get_size(&self) -> usize {
SIZE_OF_POINTER SIZE_OF_POINTER
@ -203,6 +202,9 @@ impl CFnInfo {
} }
impl LuaUserData for CFnInfo { impl LuaUserData for CFnInfo {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("size", |_, _| Ok(SIZE_OF_POINTER));
}
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
// Subtype // Subtype
method_provider::provide_ptr(methods); method_provider::provide_ptr(methods);

View file

@ -124,7 +124,7 @@ impl CPtrInfo {
impl LuaUserData for CPtrInfo { impl LuaUserData for CPtrInfo {
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", |_, _| Ok(size_of::<usize>())); fields.add_field_method_get("size", |_, _| Ok(SIZE_OF_POINTER));
fields.add_field_function_get("inner", |lua, this| { fields.add_field_function_get("inner", |lua, this| {
let inner = association::get(lua, CPTR_INNER, this)? let inner = association::get(lua, CPTR_INNER, this)?
.ok_or_else(|| LuaError::external("inner type not found"))?; .ok_or_else(|| LuaError::external("inner type not found"))?;

View file

@ -31,6 +31,9 @@ impl CVoidInfo {
} }
impl LuaUserData for CVoidInfo { impl LuaUserData for CVoidInfo {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("size", |_, _| Ok(0));
}
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
method_provider::provide_to_string(methods); method_provider::provide_to_string(methods);
method_provider::provide_ptr(methods); method_provider::provide_ptr(methods);

View file

@ -99,6 +99,24 @@ create_tests! {
datetime_to_universal_time: "datetime/toUniversalTime", datetime_to_universal_time: "datetime/toUniversalTime",
} }
#[cfg(feature = "std-ffi")]
create_tests! {
ffi_external_closure_call_closure: "ffi/external_closure/callClosure",
ffi_external_closure_call_closure_with_pointer: "ffi/external_closure/callClosureWithPointer",
ffi_external_closure_call_hello_world: "ffi/external_closure/callHelloWorld",
ffi_external_math_add_int: "ffi/external_math/addInt",
ffi_external_math_mul_int: "ffi/external_math/mulInt",
ffi_external_pointer_pointer_read: "ffi/external_pointer/pointerRead",
ffi_external_pointer_pointer_write: "ffi/external_pointer/pointerWrite",
ffi_external_print_hello_world: "ffi/external_print/helloWorld",
ffi_external_struct_ab: "ffi/external_struct/ab",
ffi_cast: "ffi/cast",
ffi_is_integer: "ffi/isInteger",
ffi_pretty_print: "ffi/prettyPrint",
ffi_read_boundary: "ffi/readBoundary",
ffi_write_boundary: "ffi/writeBoundary",
}
#[cfg(feature = "std-fs")] #[cfg(feature = "std-fs")]
create_tests! { create_tests! {
fs_files: "fs/files", fs_files: "fs/files",

View file

@ -1,12 +0,0 @@
local ffi = require("@lune/ffi")
print(ffi.int)
print(ffi.int:ptr())
print(ffi.int:arr(5):ptr())
print(ffi.int:arr(5))
print(ffi.funcInfo({ ffi.int }, ffi.int))
print(ffi.funcInfo({ ffi.int, ffi.double }, ffi.int:ptr()))
print(ffi.funcInfo({ ffi.int, ffi.double }, ffi.int:ptr():ptr()))
print(ffi.structInfo({ ffi.int, ffi.char }))

View file

@ -1,5 +1,5 @@
import { libSuffix } from "../../utility/deno.ts"; import { libSuffix } from "../../utils/libSuffix.ts";
import { get_clock, get_offset } from "../../utility/proc_clock/deno.ts"; import { get_clock, get_offset } from "../../utils/proc_clock/deno.ts";
const library_file = "./tests/ffi/benchmark/external_call/lib."+libSuffix; const library_file = "./tests/ffi/benchmark/external_call/lib."+libSuffix;
// @ts-ignore // @ts-ignore

View file

@ -1,35 +1,27 @@
local ffi = require("@lune/ffi") local ffi = require("@lune/ffi")
local lib = require("../../utility/compile")("./tests/ffi/benchmark/external_call/lib.c")
local process = require("@lune/process")
local c = ffi.c local c = ffi.c
local BENCH_SCALE: number = tonumber(process.env.BENCH_SCALE) or 1000000
local proc_clock = require("../../utility/proc_clock") -- Get clock provider
local before, after = proc_clock.newBox() local procClock = require("../../utility/proc_clock")
local get_clock = proc_clock.getClock local before, after = procClock.newBox()
local getClock = procClock.getClock
local testdir = "./tests/ffi/benchmark/external_call" local add = c.fn({ c.int, c.int }, c.int):callable(lib:find("add"))
local compile = require("../../utility/compile")
compile(`{testdir}/lib.c`, `{testdir}/lib.so`)
local lib = ffi.open(`{testdir}/lib.so`)
local function bench_add(bench_scale: number) local a = c.int:box(0)
local add_info = c.fn({ c.int, c.int }, c.int) local delta = c.int:box(1)
local a_ref = a:ref()
local delta_ref = delta:ref()
local add_callable = add_info:callable(lib:find("add")) getClock(before)
for i = 1, BENCH_SCALE do
local a = c.int:box(0) add(a, a_ref, delta_ref)
local delta = c.int:box(1)
local a_ref = a:ref()
local delta_ref = delta:ref()
get_clock(before)
for i = 1, bench_scale do
add_callable(a, a_ref, delta_ref)
end
get_clock(after)
print(proc_clock.getOffset(before, after))
local result = c.int:readData(a)
assert(result == bench_scale, `bench_add failed. result expected {bench_scale}, got {result}`)
end end
getClock(after)
bench_add(1000000) print(procClock.getOffset(before, after))
local result = c.int:readData(a)
assert(result == BENCH_SCALE, `bench_add failed. result expected {BENCH_SCALE}, got {result}`)

View file

@ -2,26 +2,23 @@
--!nocheck --!nocheck
local ffi = require("ffi") local ffi = require("ffi")
local BENCH_SCALE = 1000000
local function bench_add(bench_scale) ffi.cdef([[
ffi.cdef([[ int add(int a, int b);
int add(int a, int b); ]])
]]) local lib = ffi.load("./tests/ffi/benchmark/external_call/lib.so")
local lib = ffi.load("./tests/ffi/benchmark/external_call/lib.so") local add = lib.add
local add = lib.add local a = 0
local a = 0
local before = os.clock() local before = os.clock()
for i = 1, bench_scale do for i = 1, BENCH_SCALE do
a = add(a, 1) a = add(a, 1)
end
local after = os.clock()
print(after - before)
assert(
a == bench_scale,
string.format("bench_add failed. result expected %d, got %d", bench_scale, a)
)
end end
local after = os.clock()
bench_add(1000000) print(after - before)
assert(
a == BENCH_SCALE,
string.format("bench_add failed. result expected %d, got %d", BENCH_SCALE, a)
)

View file

@ -0,0 +1,14 @@
local callableWrapper = require("../utils/callableWrapper")
local ffi = require("@lune/ffi")
local lib = require("../utils/compile")("./tests/ffi/external_closure/lib.c")
local c = ffi.c
-- Create closure
local closureInfo = c.fn({ c.int, c.int }, c.int)
local closure = closureInfo:closure(function(ret, a, b)
c.int:writeData(ret, c.int:readData(a) + c.int:readData(b))
end)
local callClosure = callableWrapper(lib:find("call_closure"), { closureInfo }, c.int)
local result = callClosure(closure:ref())
assert(result == 72, `callClosure failed. result expected 20000, got {result}`)

View file

@ -0,0 +1,15 @@
local callableWrapper = require("../utils/callableWrapper")
local ffi = require("@lune/ffi")
local lib = require("../utils/compile")("./tests/ffi/external_closure/lib.c")
local c = ffi.c
-- Create closure
local closureWithPointerInfo = c.fn({ c.int, c.int:ptr() }, c.int)
local closureWithPointer = closureWithPointerInfo:closure(function(returnRef, aRef, bRef)
c.int:writeData(returnRef, c.int:readData(aRef) + c.int:readData(bRef:deref()))
end)
local callClosureWithPointer =
callableWrapper(lib:find("call_closure_with_pointer"), { closureWithPointerInfo }, c.int)
local result = callClosureWithPointer(closureWithPointer:ref())
assert(result == 72, `closureWithPointer failed. result expected 20000, got {result}`)

View file

@ -0,0 +1,12 @@
local ffi = require("@lune/ffi")
local lib = require("../utils/compile")("./tests/ffi/external_closure/lib.c")
local c = ffi.c
-- Create closure
local helloWorldInfo = c.fn({}, c.void)
local helloWorld = helloWorldInfo:closure(function()
print("Hello world in lua closure!")
end)
local callHelloWorld = c.fn({ helloWorldInfo }, c.void):callable(lib:find("call_hello_world"))
callHelloWorld(nil, helloWorld:ref())

View file

@ -1,52 +0,0 @@
local ffi = require("@lune/ffi")
local c = ffi.c
local testdir = "./tests/ffi/external_closure"
local compile = require("../utility/compile")
compile(`{testdir}/lib.c`, `{testdir}/lib.so`)
local lib = ffi.open(`{testdir}/lib.so`)
local function test_callClosure()
local closureInfo = c.fn({ c.int, c.int }, c.int)
local closure = closureInfo:closure(function(ret, a, b)
c.int:writeData(ret, c.int:readData(a) + c.int:readData(b))
end)
local callClosure = c.fn({ closureInfo }, c.int):callable(lib:find("call_closure"))
local resultBox = ffi.box(c.int.size)
callClosure(resultBox, closure:ref())
local result = c.int:readData(resultBox)
assert(result == 72, `test_callClosure failed. result expected 20000, got {result}`)
end
test_callClosure()
local function test_helloWorld()
local helloWorldInfo = c.fn({}, c.void)
local helloWorld = helloWorldInfo:closure(function()
print("Hello world in lua closure!")
end)
local callHelloWorld = c.fn({ helloWorldInfo }, c.void):callable(lib:find("call_hello_world"))
callHelloWorld(nil, helloWorld:ref())
end
test_helloWorld()
local function test_closureWithPointer()
local closureWithPointerInfo = c.fn({ c.int, c.int:ptr() }, c.int)
local closureWithPointer = closureWithPointerInfo:closure(function(returnRef, aRef, bRef)
c.int:writeData(returnRef, c.int:readData(aRef) + c.int:readData(bRef:deref()))
end)
local callClosureWithPointer = c.fn({ closureWithPointerInfo }, c.int)
:callable(lib:find("call_closure_with_pointer"))
local resultBox = ffi.box(c.int.size)
callClosureWithPointer(resultBox, closureWithPointer:ref())
local result = c.int:readData(resultBox)
assert(result == 72, `test_closureWithPointer failed. result expected 20000, got {result}`)
end
test_closureWithPointer()

View file

@ -0,0 +1,9 @@
local callableWrapper = require("../utils/callableWrapper")
local ffi = require("@lune/ffi")
local lib = require("../utils/compile")("./tests/ffi/external_math/lib.c")
local c = ffi.c
local addInt = callableWrapper(lib:find("add_int"), { c.int, c.int }, c.int)
local result = addInt(100, 200)
assert(result == 300, `test_addInt failed. result expected 300, got {result}`)

View file

@ -1,37 +0,0 @@
local ffi = require("@lune/ffi")
local c = ffi.c
local testdir = "./tests/ffi/external_math"
local compile = require("../utility/compile")
compile(`{testdir}/lib.c`, `{testdir}/lib.so`)
local lib = ffi.open(`{testdir}/lib.so`)
local function test_addInt()
local addInt = c.fn({ c.int, c.int }, c.int):callable(lib:find("add_int"))
local resultBox = ffi.box(c.int.size)
local arg1 = c.int:box(100)
local arg2 = c.int:box(200)
addInt(resultBox, arg1:ref(), arg2:ref())
local result = c.int:readData(resultBox)
assert(result == 300, `test_addInt failed. result expected 300, got {result}`)
end
test_addInt()
local function test_mulInt()
local mulInt = c.fn({ c.int, c.int }, c.int):callable(lib:find("mul_int"))
local resultBox = ffi.box(c.int.size)
local arg1 = c.int:box(100)
local arg2 = c.int:box(200)
mulInt(resultBox, arg1:ref(), arg2:ref())
local result = c.int:readData(resultBox)
assert(result == 20000, `test_mulInt failed. result expected 20000, got {result}`)
end
test_mulInt()

View file

@ -0,0 +1,8 @@
local callableWrapper = require("../utils/callableWrapper")
local ffi = require("@lune/ffi")
local lib = require("../utils/compile")("./tests/ffi/external_math/lib.c")
local c = ffi.c
local mulInt = callableWrapper(lib:find("mul_int"), { c.int, c.int }, c.int)
local result = mulInt(100, 200)
assert(result == 20000, `test_mulInt failed. result expected 20000, got {result}`)

View file

@ -1,20 +0,0 @@
local ffi = require("@lune/ffi")
local c = ffi.c
local testdir = "./tests/ffi/external_pointer"
local compile = require("../utility/compile")
compile(`{testdir}/lib.c`, `{testdir}/lib.so`)
local lib = ffi.open(`{testdir}/lib.so`)
local function test_pointerWrite()
local pointerWrite = c.fn({ c.int:ptr() }, c.void):callable(lib:find("pointer_write"))
local aBox = ffi.box(c.int.size)
pointerWrite(nil, aBox:ref():ref())
local result = c.int:readData(aBox)
assert(result == 123, `pointer failed. result expected 123, got {result}`)
end
test_pointerWrite()

View file

@ -1,3 +1,7 @@
void pointer_write(int *a) { void pointer_write(int *a) {
*a = 123; *a = 123;
} }
int pointer_read(int *a) {
return *a;
}

View file

@ -0,0 +1,8 @@
local callableWrapper = require("../utils/callableWrapper")
local ffi = require("@lune/ffi")
local lib = require("../utils/compile")("./tests/ffi/external_pointer/lib.c")
local c = ffi.c
local pointerRead = callableWrapper(lib:find("pointer_read"), { c.int:ptr() }, c.int)
local result = pointerRead(c.int:box(123):ref():ref())
assert(result == 123, `pointerRead failed. result expected 123, got {result}`)

View file

@ -0,0 +1,9 @@
local ffi = require("@lune/ffi")
local lib = require("../utils/compile")("./tests/ffi/external_pointer/lib.c")
local c = ffi.c
local pointerWrite = c.fn({ c.int:ptr() }, c.void):callable(lib:find("pointer_write"))
local aBox = ffi.box(c.int.size)
pointerWrite(nil, aBox:ref():ref())
local result = c.int:readData(aBox)
assert(result == 123, `pointerWrite failed. result expected 123, got {result}`)

View file

@ -0,0 +1,5 @@
local ffi = require("@lune/ffi")
local lib = require("../utils/compile")("./tests/ffi/external_print/lib.c")
local c = ffi.c
c.fn({}, c.void):callable(lib:find("hello_world"))(nil)

View file

@ -1,17 +0,0 @@
local ffi = require("@lune/ffi")
local c = ffi.c
local testdir = "./tests/ffi/external_print"
local compile = require("../utility/compile")
compile(`{testdir}/lib.c`, `{testdir}/lib.so`)
local lib = ffi.open(`{testdir}/lib.so`)
local function test_hello_world()
local hello_world_info = c.fn({}, c.void)
local hello_world_callable = hello_world_info:callable(lib:find("hello_world"))
hello_world_callable(nil)
end
test_hello_world()

View file

@ -0,0 +1,12 @@
local callableWrapper = require("../utils/callableWrapper")
local ffi = require("@lune/ffi")
local lib = require("../utils/compile")("./tests/ffi/external_struct/lib.c")
local c = ffi.c
local argStructInfo = c.struct({ c.int, c.int:ptr() })
local resultStructInfo = c.struct({ c.int, c.int })
local ab = callableWrapper(lib:find("ab"), { argStructInfo }, resultStructInfo)
local result = ab({ 100, c.int:box(200):ref() } :: { any })
assert(result[1] == 300, `ab failed. result expected 300, got {result[1]}`)
assert(result[2] == 20000, `ab failed. result expected 300, got {result[2]}`)

View file

@ -1,28 +0,0 @@
local ffi = require("@lune/ffi")
local c = ffi.c
local testdir = "./tests/ffi/external_struct"
local compile = require("../utility/compile")
compile(`{testdir}/lib.c`, `{testdir}/lib.so`)
local lib = ffi.open(`{testdir}/lib.so`)
local function test_AB()
local argStructInfo = c.struct({ c.int, c.int:ptr() })
local resultStructInfo = c.struct({ c.int, c.int })
local AB = c.fn({ argStructInfo }, resultStructInfo)
local AB_callable = AB:callable(lib:find("AB"))
local resultBox = ffi.box(resultStructInfo.size)
local b = c.int:box(200)
local argStruct = argStructInfo:box({ 100, b:ref() })
AB_callable(resultBox, argStruct:ref())
local result = resultStructInfo:readData(resultBox)
assert(result[1] == 300, `AB failed. result expected 300, got {result[1]}`)
assert(result[2] == 20000, `AB failed. result expected 300, got {result[2]}`)
end
test_AB()

View file

@ -8,7 +8,7 @@ typedef struct {
int mul; int mul;
} ResultStruct; } ResultStruct;
ResultStruct AB(ArgStruct t) { ResultStruct ab(ArgStruct t) {
ResultStruct result = { t.a+ * t.b, t.a * (*t.b) }; ResultStruct result = { t.a+ * t.b, t.a * (*t.b) };
return result; return result;
} }

View file

@ -1,5 +1,4 @@
local ffi = require("@lune/ffi") local ffi = require("@lune/ffi")
local ok local ok
-- Case1: Success -- Case1: Success
@ -24,7 +23,6 @@ end)
assert(ok, "assersion failed, Case3 should success") assert(ok, "assersion failed, Case3 should success")
-- Case4: Success -- Case4: Success
ok = pcall(function() ok = pcall(function()
local box = ffi.box(ffi.u8.size * 2) local box = ffi.box(ffi.u8.size * 2)
ffi.u8:readData(box, ffi.u8.size) ffi.u8:readData(box, ffi.u8.size)

View file

@ -1,9 +0,0 @@
local process = require("@lune/process")
local function compile(file, out)
local gcc = process.exec("gcc", { "-shared", "-o", out, "-fPIC", file })
if not gcc.ok then
error("Failed to execute gcc command\n" .. gcc.stdout .. gcc.stderr)
end
end
return compile

View file

@ -0,0 +1,38 @@
--!nocheck
local ffi = require("@lune/ffi")
local function callableWrapper(
functionRef: ffi.RefData,
argTypeList: { ffi.CTypes },
retType: ffi.CTypes
): (...any) -> any
local callable = ffi.c.fn(argTypeList, retType):callable(functionRef)
return function(...)
local argValues = table.create(#argTypeList + 1)
local resultBox
if retType ~= ffi.c.void then
resultBox = ffi.box(retType.size)
end
argValues[1] = resultBox
for index, argType in argTypeList do
local arg = select(index, ...)
if type(arg) == "userdata" then
argValues[index + 1] = arg
else
argValues[index + 1] = argType:box(arg):ref()
end
end
callable(table.unpack(argValues, 1, #argTypeList + 1))
if retType == ffi.c.void then
return nil
end
return retType:readData(resultBox)
end
end
return callableWrapper

View file

@ -0,0 +1,25 @@
local ffi = require("@lune/ffi")
local process = require("@lune/process")
local function getLibSuffix(): string
if process.os == "linux" then
return "so"
elseif process.os == "windows" then
return "dll"
elseif process.os == "macos" then
return "dylib"
end
error("Unknown OS")
end
local function compile(file: string): ffi.LibData
local out = file:gsub("%.c$", "." .. getLibSuffix())
local gcc = process.exec("gcc", { "-shared", "-o", out, "-fPIC", file })
if not gcc.ok then
error("Failed to execute gcc command\n" .. gcc.stdout .. gcc.stderr)
end
return ffi.open(out)
end
return compile

View file

@ -1,6 +1,6 @@
import { libSuffix } from "../deno.ts"; import { libSuffix } from "../libSuffix.ts";
const library_file = "./tests/ffi/utility/proc_clock/lib."+libSuffix; const library_file = "./tests/ffi/utils/proc_clock/lib."+libSuffix;
// @ts-ignore // @ts-ignore
let library = Deno.dlopen(library_file, { let library = Deno.dlopen(library_file, {
sizeof_clock: { sizeof_clock: {

View file

@ -7,10 +7,7 @@ local c = ffi.c
local procClock = {} local procClock = {}
local libdir = "./tests/ffi/utility/proc_clock" local lib = require("../compile")("./tests/ffi/utils/proc_clock/lib.c")
local compile = require("../compile")
compile(`{libdir}/lib.c`, `{libdir}/lib.so`)
local lib = ffi.open(`{libdir}/lib.so`)
-- sizeof_clock -- sizeof_clock
local sizeofClock = c.fn({}, c.int):callable(lib:find("sizeof_clock")) local sizeofClock = c.fn({}, c.int):callable(lib:find("sizeof_clock"))

View file

@ -1,6 +1,5 @@
local ffi = require("@lune/ffi") local ffi = require("@lune/ffi")
local c = ffi.c local c = ffi.c
local ok local ok
-- Case1: Fail -- Case1: Fail

View file

@ -42,15 +42,13 @@ local ffi = {}
--[=[ --[=[
@class C @class C
@within FFI
Namespace for compile time sized c types. Namespace for compile time sized c types.
]=] ]=]
local c = {} local c = {}
ffi.c = c ffi.c = c
--#region Data -- --#region Data
--[=[ --[=[
@class RefData @class RefData
@ -124,7 +122,13 @@ export type RefData = {
@param dst_offset The offset in the destination where the data will be pasted @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 @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)->(); copyFrom: (
self: RefData,
src: BoxData | RefData,
length: number,
dst_offset: number,
src_offset: number
) -> (),
} }
--[=[ --[=[
@ -190,7 +194,13 @@ export type BoxData = {
@param dst_offset The offset in the destination where the data will be pasted @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 @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)->(); copyFrom: (
self: BoxData,
src: BoxData | RefData,
length: number,
dst_offset: number,
src_offset: number
) -> (),
} }
--[=[ --[=[
@ -223,7 +233,10 @@ export type LibData = {
If return type is `void`, pass `nil`. If return type is `void`, pass `nil`.
]=] ]=]
export type CallableData = (ret: (RefData|BoxData)?, ...RefData)->() & { export type CallableData = (
ret: (RefData | BoxData)?,
...RefData
) -> () & {
-- apply: (self: Callable, args: Args)->AppliedCallable, -- apply: (self: Callable, args: Args)->AppliedCallable,
} }
@ -246,13 +259,11 @@ export type ClosureData = {
@return A reference of the closure @return A reference of the closure
]=] ]=]
ref: (self: ClosureData)->RefData, ref: (self: ClosureData) -> RefData,
} }
--#endregion Data
--#endregion Data -- --#region C ABI Type Infos
--#region C ABI Type Infos --
-- NOTE: T is a unique identifier for the `CType` and R is the closest Lua type. -- NOTE: T is a unique identifier for the `CType` and R is the closest Lua type.
export type CTypeInfo<T, R> = { export type CTypeInfo<T, R> = {
--[=[ --[=[
@ -278,14 +289,19 @@ export type CTypeInfo<T, R> = {
-- realize -- realize
box: (self: CTypeInfo<T, R>, val: R) -> BoxData, box: (self: CTypeInfo<T, R>, val: R) -> BoxData,
readData: (self: CTypeInfo<T, R>, target: (RefData|BoxData), offset: number?) -> R, readData: (self: CTypeInfo<T, R>, target: RefData | BoxData, offset: number?) -> R,
writeData: (self: CTypeInfo<T, R>, target: (RefData|BoxData), value: R, offset: number?) -> (), writeData: (self: CTypeInfo<T, R>, target: RefData | BoxData, value: R, offset: number?) -> (),
stringifyData: (self: CTypeInfo<T, R>, target: (RefData|BoxData), offset: number?) -> string, stringifyData: (self: CTypeInfo<T, R>, target: RefData | BoxData, offset: number?) -> string,
-- FIXME: recursive types; 'intoType' should be CTypes -- FIXME: recursive types; 'intoType' should be CTypes
cast: (self: CTypeInfo<T, R>, intoType: any, fromData: (RefData|BoxData), intoData: (RefData|BoxData)) -> (), cast: (
self: CTypeInfo<T, R>,
intoType: any,
fromData: RefData | BoxData,
intoData: RefData | BoxData
) -> (),
} & { ["__phantom"]: T } } & { ["__phantom"]: T }
type NumCType<T> = CTypeInfo<T, (number|any)> type NumCType<T> = CTypeInfo<T, (number | any)>
export type CPtrInfo<T> = { export type CPtrInfo<T> = {
--[=[ --[=[
@ -313,8 +329,13 @@ export type CPtrInfo<T> = {
-- FIXME: recursive types; result 'any' should be CPtrInfo<CPtrInfo<T>> -- FIXME: recursive types; result 'any' should be CPtrInfo<CPtrInfo<T>>
ptr: (self: CPtrInfo<T>) -> any, ptr: (self: CPtrInfo<T>) -> any,
readRef: (self: CPtrInfo<T>, target: (RefData|BoxData), offset: number?) -> RefData, readRef: (self: CPtrInfo<T>, target: RefData | BoxData, offset: number?) -> RefData,
writeRef: (self: CPtrInfo<T>, target: (RefData|BoxData), value: (RefData|BoxData), offset: number?) -> (), writeRef: (
self: CPtrInfo<T>,
target: RefData | BoxData,
value: RefData | BoxData,
offset: number?
) -> (),
} }
--[=[ --[=[
@ -353,9 +374,20 @@ export type CArrInfo<T, R> = {
-- realize -- realize
box: (self: CArrInfo<T, R>, table: { T }) -> BoxData, box: (self: CArrInfo<T, R>, table: { T }) -> BoxData,
readData: (self: CArrInfo<T, R>, target: (RefData|BoxData), offset: number?) -> { T }, readData: (self: CArrInfo<T, R>, target: RefData | BoxData, offset: number?) -> { T },
writeData: (self: CArrInfo<T, R>, target: (RefData|BoxData), value: { R }, target_offset: number?) -> (), writeData: (
copyData: (self: CArrInfo<T, R>, dst: (RefData|BoxData), src: (RefData|BoxData), dst_offset: number?, src_offset: number?) -> (), self: CArrInfo<T, R>,
target: RefData | BoxData,
value: { R },
target_offset: number?
) -> (),
copyData: (
self: CArrInfo<T, R>,
dst: RefData | BoxData,
src: RefData | BoxData,
dst_offset: number?,
src_offset: number?
) -> (),
offset: (self: CArrInfo<T, R>, index: number) -> number, offset: (self: CArrInfo<T, R>, index: number) -> number,
} }
@ -366,6 +398,16 @@ export type CArrInfo<T, R> = {
A c function signature type information. A c function signature type information.
]=] ]=]
export type CFnInfo = { export type CFnInfo = {
--[=[
@within CFnInfo
@tag Field
@field size
The size of a function pointer.
Equivalent to `ffi.c.usize.size`.
]=]
size: number,
--[=[ --[=[
@within CFnInfo @within CFnInfo
@tag Method @tag Method
@ -385,7 +427,7 @@ export type CFnInfo = {
@return A closure. @return A closure.
]=] ]=]
closure: (self: CFnInfo, (ret: RefData, ...RefData)->()) -> ClosureData, closure: (self: CFnInfo, (ret: RefData, ...RefData) -> ()) -> ClosureData,
} }
--[=[ --[=[
@ -394,6 +436,13 @@ export type CFnInfo = {
A c struct type information. A c struct type information.
]=] ]=]
export type CStructInfo = { export type CStructInfo = {
--[=[
@within CStructInfo
@tag Field
@field size
The size of a struct, including padding.
]=]
size: number, size: number,
--[=[ --[=[
@ -406,7 +455,7 @@ export type CStructInfo = {
@param len The length of the array @param len The length of the array
@return A struct array type @return A struct array type
]=] ]=]
arr: (self: CStructInfo, len: number) -> CArrInfo<CStructInfo, {any}>, arr: (self: CStructInfo, len: number) -> CArrInfo<CStructInfo, { any }>,
--[=[ --[=[
@within CSturctInfo @within CSturctInfo
@tag Method @tag Method
@ -419,9 +468,20 @@ export type CStructInfo = {
ptr: (self: CStructInfo) -> CPtrInfo<CStructInfo>, ptr: (self: CStructInfo) -> CPtrInfo<CStructInfo>,
box: (self: CStructInfo, table: { any }) -> BoxData, box: (self: CStructInfo, table: { any }) -> BoxData,
readData: (self: CStructInfo, target: (RefData|BoxData), offset: number?) -> { any }, readData: (self: CStructInfo, target: RefData | BoxData, offset: number?) -> { any },
writeData: (self: CStructInfo, target: (RefData|BoxData), table: { any }, offset: number?) -> (), writeData: (
copyData: (self: CStructInfo, dst: (RefData|BoxData), src: (RefData|BoxData), dst_offset: number?, src_offset: number?) -> (), self: CStructInfo,
target: RefData | BoxData,
table: { any },
offset: number?
) -> (),
copyData: (
self: CStructInfo,
dst: RefData | BoxData,
src: RefData | BoxData,
dst_offset: number?,
src_offset: number?
) -> (),
offset: (self: CStructInfo, index: number) -> number, offset: (self: CStructInfo, index: number) -> number,
field: (self: CStructInfo, index: number) -> CTypes, field: (self: CStructInfo, index: number) -> CTypes,
@ -433,6 +493,14 @@ export type CStructInfo = {
A type that represents c void. can only be used for the function return type. A type that represents c void. can only be used for the function return type.
]=] ]=]
export type CVoidInfo = { export type CVoidInfo = {
--[=[
@within CVoidInfo
@tag Field
@field size
The size of the void type. It is always 0.
]=]
size: number,
--[=[ --[=[
@within CVoidInfo @within CVoidInfo
@tag Method @tag Method
@ -445,13 +513,11 @@ export type CVoidInfo = {
ptr: (self: CVoidInfo) -> CPtrInfo<CVoidInfo>, ptr: (self: CVoidInfo) -> CPtrInfo<CVoidInfo>,
} }
c.void = {} :: CVoidInfo c.void = {} :: CVoidInfo
--#endregion C ABI Type Infos
--#endregion C ABI Type Infos -- --#region Fixed size Rust-style types
--#region Fixed size Rust-style types --
--[=[ --[=[
@class u8 @prop u8 NumCType
@within FFI @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`.
@ -459,7 +525,7 @@ c.void = {} :: CVoidInfo
ffi.u8 = {} :: u8 ffi.u8 = {} :: u8
export type u8 = NumCType<"u8"> export type u8 = NumCType<"u8">
--[=[ --[=[
@class u16 @prop u16 NumCType
@within FFI @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`.
@ -467,7 +533,7 @@ export type u8 = NumCType<"u8">
ffi.u16 = {} :: u16 ffi.u16 = {} :: u16
export type u16 = NumCType<"u16"> export type u16 = NumCType<"u16">
--[=[ --[=[
@class u32 @prop u32 NumCType
@within FFI @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`.
@ -475,7 +541,7 @@ export type u16 = NumCType<"u16">
ffi.u32 = {} :: u32 ffi.u32 = {} :: u32
export type u32 = NumCType<"u32"> export type u32 = NumCType<"u32">
--[=[ --[=[
@class u64 @prop u64 NumCType
@within FFI @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`.
@ -483,7 +549,7 @@ export type u32 = NumCType<"u32">
ffi.u64 = {} :: u64 ffi.u64 = {} :: u64
export type u64 = NumCType<"u64"> export type u64 = NumCType<"u64">
--[=[ --[=[
@class u128 @prop u128 NumCType
@within FFI @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`.
@ -491,7 +557,7 @@ export type u64 = NumCType<"u64">
ffi.u128 = {} :: u128 ffi.u128 = {} :: u128
export type u128 = NumCType<"u128"> export type u128 = NumCType<"u128">
--[=[ --[=[
@class i8 @prop i8 NumCType
@within FFI @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`.
@ -499,7 +565,7 @@ export type u128 = NumCType<"u128">
ffi.i8 = {} :: i8 ffi.i8 = {} :: i8
export type i8 = NumCType<"i8"> export type i8 = NumCType<"i8">
--[=[ --[=[
@class i16 @prop i16 NumCType
@within FFI @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`.
@ -507,7 +573,7 @@ export type i8 = NumCType<"i8">
ffi.i16 = {} :: i16 ffi.i16 = {} :: i16
export type i16 = NumCType<"i16"> export type i16 = NumCType<"i16">
--[=[ --[=[
@class i32 @prop i32 NumCType
@within FFI @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`.
@ -515,7 +581,7 @@ export type i16 = NumCType<"i16">
ffi.i32 = {} :: i32 ffi.i32 = {} :: i32
export type i32 = NumCType<"i32"> export type i32 = NumCType<"i32">
--[=[ --[=[
@class i64 @prop i64 NumCType
@within FFI @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`.
@ -523,7 +589,7 @@ export type i32 = NumCType<"i32">
ffi.i64 = {} :: i64 ffi.i64 = {} :: i64
export type i64 = NumCType<"i64"> export type i64 = NumCType<"i64">
--[=[ --[=[
@class i128 @prop i128 NumCType
@within FFI @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`.
@ -531,7 +597,7 @@ export type i64 = NumCType<"i64">
ffi.i128 = {} :: i128 ffi.i128 = {} :: i128
export type i128 = NumCType<"i128"> export type i128 = NumCType<"i128">
--[=[ --[=[
@class f32 @prop f32 NumCType
@within FFI @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.
@ -539,7 +605,7 @@ export type i128 = NumCType<"i128">
ffi.f32 = {} :: f32 ffi.f32 = {} :: f32
export type f32 = NumCType<"f32"> export type f32 = NumCType<"f32">
--[=[ --[=[
@class f64 @prop f64 NumCType
@within FFI @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.
@ -547,7 +613,7 @@ export type f32 = NumCType<"f32">
ffi.f64 = {} :: f64 ffi.f64 = {} :: f64
export type f64 = NumCType<"f64"> export type f64 = NumCType<"f64">
--[=[ --[=[
@class usize @prop usize NumCType
@within FFI @within FFI
A machine specific pointer sized unsigned integer. A machine specific pointer sized unsigned integer.
@ -555,19 +621,18 @@ export type f64 = NumCType<"f64">
ffi.usize = {} :: usize ffi.usize = {} :: usize
export type usize = NumCType<"usize"> export type usize = NumCType<"usize">
--[=[ --[=[
@class isize @prop isize NumCType
@within FFI @within FFI
A machine specific pointer sized signed integer. A machine specific pointer sized signed integer.
]=] ]=]
ffi.isize = {} :: isize ffi.isize = {} :: isize
export type isize = NumCType<"isize"> export type isize = NumCType<"isize">
--#endregion Fixed size Rust-style types
--#endregion Fixed size Rust-style types -- --#region Variable size C-style types
--#region Variable size C-style types --
--[=[ --[=[
@class char @prop char NumCType
@within C @within C
Compiler defined C `char` type. Compiler defined C `char` type.
@ -578,12 +643,8 @@ export type isize = NumCType<"isize">
]=] ]=]
c.char = {} :: char c.char = {} :: char
export type char = NumCType<"char"> export type char = NumCType<"char">
-- c.float = {} :: float
-- export type float = NumCType<"float">
-- c.double = {} :: double
-- export type double = NumCType<"double">
--[=[ --[=[
@class uchar @prop uchar NumCType
@within C @within C
Compiler defined C `unsigned char` type. Compiler defined C `unsigned char` type.
@ -593,7 +654,7 @@ export type char = NumCType<"char">
c.uchar = {} :: uchar c.uchar = {} :: uchar
export type uchar = NumCType<"uchar"> export type uchar = NumCType<"uchar">
--[=[ --[=[
@class schar @prop schar NumCType
@within C @within C
Compiler defined C `signed char` type. Compiler defined C `signed char` type.
@ -601,7 +662,7 @@ export type uchar = NumCType<"uchar">
c.schar = {} :: schar c.schar = {} :: schar
export type schar = NumCType<"schar"> export type schar = NumCType<"schar">
--[=[ --[=[
@class short @prop short NumCType
@within C @within C
Compiler defined C `short` type. Compiler defined C `short` type.
@ -609,7 +670,7 @@ export type schar = NumCType<"schar">
c.short = {} :: short c.short = {} :: short
export type short = NumCType<"short"> export type short = NumCType<"short">
--[=[ --[=[
@class ushort @prop ushort NumCType
@within C @within C
Compiler defined C `unsigned short` type. Compiler defined C `unsigned short` type.
@ -617,7 +678,7 @@ export type short = NumCType<"short">
c.ushort = {} :: ushort c.ushort = {} :: ushort
export type ushort = NumCType<"ushort"> export type ushort = NumCType<"ushort">
--[=[ --[=[
@class int @prop int NumCType
@within C @within C
Compiler defined C `int` type. Compiler defined C `int` type.
@ -627,7 +688,7 @@ export type ushort = NumCType<"ushort">
c.int = {} :: int c.int = {} :: int
export type int = NumCType<"int"> export type int = NumCType<"int">
--[=[ --[=[
@class uint @prop uint NumCType
@within C @within C
Compiler defined C `unsigned int` type. Compiler defined C `unsigned int` type.
@ -637,7 +698,7 @@ export type int = NumCType<"int">
c.uint = {} :: uint c.uint = {} :: uint
export type uint = NumCType<"uint"> export type uint = NumCType<"uint">
--[=[ --[=[
@class long @prop long NumCType
@within C @within C
Compiler defined C `long` type. Compiler defined C `long` type.
@ -647,7 +708,7 @@ export type uint = NumCType<"uint">
c.long = {} :: long c.long = {} :: long
export type long = NumCType<"long"> export type long = NumCType<"long">
--[=[ --[=[
@class ulong @prop ulong NumCType
@within C @within C
Compiler defined C `unsigned long` type. Compiler defined C `unsigned long` type.
@ -657,7 +718,7 @@ export type long = NumCType<"long">
c.ulong = {} :: ulong c.ulong = {} :: ulong
export type ulong = NumCType<"ulong"> export type ulong = NumCType<"ulong">
--[=[ --[=[
@class longlong @prop longlong NumCType
@within C @within C
Compiler defined C `unsigned longlong` type. Compiler defined C `unsigned longlong` type.
@ -665,15 +726,14 @@ export type ulong = NumCType<"ulong">
c.longlong = {} :: longlong c.longlong = {} :: longlong
export type longlong = NumCType<"longlong"> export type longlong = NumCType<"longlong">
--[=[ --[=[
@class longlong @prop longlong NumCType
@within C @within C
Compiler defined C `unsigned longlong` type. Compiler defined C `unsigned longlong` type.
]=] ]=]
c.ulonglong = {} :: ulonglong c.ulonglong = {} :: ulonglong
export type ulonglong = NumCType<"ulonglong"> export type ulonglong = NumCType<"ulonglong">
--#endregion Variable size C-style types
--#endregion Variable size C-style types --
--[=[ --[=[
@class CTypes @class CTypes
@ -681,7 +741,7 @@ export type ulonglong = NumCType<"ulonglong">
All possible C types. All possible C types.
]=] ]=]
export type CTypes = export type CTypes =
| u8 u8
| u16 | u16
| u32 | u32
| u64 | u64
@ -696,8 +756,6 @@ export type CTypes =
| usize | usize
| isize | isize
| char | char
-- | float
-- | double
| uchar | uchar
| schar | schar
| short | short