Skip to content

Instantly share code, notes, and snippets.

@u9g
Created February 28, 2023 00:18
Show Gist options
  • Save u9g/a9cc4782270981f30c51061de3211a26 to your computer and use it in GitHub Desktop.
Save u9g/a9cc4782270981f30c51061de3211a26 to your computer and use it in GitHub Desktop.
// type ptr = number
// enum FFIType {
// pointer = 1,
// i8,
// i16,
// i32,
// i64,
// u8,
// u16,
// u32,
// u64,
// string,
// }
import { FFIType } from "bun:ffi"
type UNTYPED = never
export type Pointer = number & {}
interface FFITypeToType {
[FFIType.char]: number
[FFIType.int8_t]: number
[FFIType.i8]: number
[FFIType.uint8_t]: number
[FFIType.u8]: number
[FFIType.int16_t]: number
[FFIType.i16]: number
[FFIType.uint16_t]: number
[FFIType.u16]: number
[FFIType.int32_t]: number
[FFIType.i32]: number
[FFIType.int]: number
[FFIType.uint32_t]: number
[FFIType.u32]: number
[FFIType.int64_t]: UNTYPED
[FFIType.i64]: UNTYPED
[FFIType.uint64_t]: UNTYPED
[FFIType.u64]: UNTYPED
[FFIType.double]: UNTYPED
[FFIType.f64]: UNTYPED
[FFIType.float]: UNTYPED
[FFIType.f32]: UNTYPED
[FFIType.bool]: boolean
[FFIType.ptr]: Pointer
[FFIType.pointer]: Pointer
[FFIType.void]: UNTYPED
[FFIType.cstring]: UNTYPED
[FFIType.i64_fast]: number | bigint
[FFIType.u64_fast]: number | bigint
}
interface FFIFunction {
args: FFIType[]
returns: FFIType
}
type _Narrow<T, U> = [U] extends [T] ? U : Extract<T, U>
type Narrow<T = unknown> =
| _Narrow<T, 0 | (number & {})>
| _Narrow<T, 0n | (bigint & {})>
| _Narrow<T, "" | (string & {})>
| _Narrow<T, boolean>
| _Narrow<T, symbol>
| _Narrow<T, []>
| _Narrow<T, { [_: PropertyKey]: Narrow }>
| (T extends object ? { [K in keyof T]: Narrow<T[K]> } : never)
| Extract<{} | null | undefined, T>
type ConvertFns<Fns extends Record<string, FFIFunction>> = {
[K in keyof Fns]: (
...args: Fns[K]["args"] extends infer A extends FFIType[]
? { [L in keyof A]: FFITypeToType[A[L]] }
: never
) => FFITypeToType[Fns[K]["returns"]]
}
export declare function dlopen<Fns extends Record<string, Narrow<FFIFunction>>>(
path: string,
functions: Fns
): { symbols: ConvertFns<Fns> }
/*
const { add } = dlopen("Ws2_32", {
add: {
names: ["first", "second"],
args: [FFIType.i32, FFIType.i8],
returns: FFIType.pointer,
},
})
type Test = typeof add // should be (first: number, second: number) => ptr
// ^? - type Test = (args_0: number, args_1: number) => number
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment