koffi
Version: 
Fast and simple C FFI (foreign function interface) for Node.js
284 lines (251 loc) • 10.9 kB
TypeScript
// Copyright (C) 2025  Niels Martignène <niels.martignene@protonmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the “Software”), to deal in
// the Software without restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
// Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
type LoadOptions = {
    lazy?: boolean,
    global?: boolean,
    deep?: boolean
};
export function load(path: string | null, options?: LoadOptions): IKoffiLib;
interface IKoffiCType { __brand: 'IKoffiCType' }
interface IKoffiPointerCast { __brand: 'IKoffiPointerCast' }
interface IKoffiRegisteredCallback { __brand: 'IKoffiRegisteredCallback' }
type PrimitiveKind = 'Void' | 'Bool' | 'Int8' | 'UInt8' | 'Int16' | 'Int16S' | 'UInt16' | 'UInt16S' |
                     'Int32' | 'Int32S' | 'UInt32' | 'UInt32S' | 'Int64' | 'Int64S' | 'UInt64' | 'UInt64S' |
                     'String' | 'String16' | 'Pointer' | 'Record' | 'Union' | 'Array' | 'Float32' | 'Float64' |
                     'Prototype' | 'Callback';
type ArrayHint = 'Array' | 'Typed' | 'String';
type TypeSpec = string | IKoffiCType;
type TypeSpecWithAlignment = TypeSpec | [number, TypeSpec];
type TypeInfo = {
    name: string;
    primitive: PrimitiveKind;
    size: number;
    alignment: number;
    disposable: boolean;
    length?: number;
    hint?: ArrayHint;
    ref?: IKoffiCType;
    members?: Record<string, { name: string, type: IKoffiCType, offset: number }>;
};
type KoffiFunction = {
    (...args: any[]) : any;
    async: (...args: any[]) => any;
    info: {
        name: string,
        arguments: IKoffiCType[],
        result: IKoffiCType
    };
};
export type KoffiFunc<T extends (...args: any) => any> = T & {
   async: (...args: [...Parameters<T>, (err: any, result: ReturnType<T>) => void]) => void;
   info: {
      name: string;
      arguments: IKoffiCType[];
      result: IKoffiCType;
   };
};
export interface IKoffiLib {
    func(definition: string): KoffiFunction;
    func(name: string | number, result: TypeSpec, arguments: TypeSpec[]): KoffiFunction;
    func(convention: string, name: string | number, result: TypeSpec, arguments: TypeSpec[]): KoffiFunction;
    /** @deprecated */ cdecl(definition: string): KoffiFunction;
    /** @deprecated */ cdecl(name: string | number, result: TypeSpec, arguments: TypeSpec[]): KoffiFunction;
    /** @deprecated */ stdcall(definition: string): KoffiFunction;
    /** @deprecated */ stdcall(name: string | number, result: TypeSpec, arguments: TypeSpec[]): KoffiFunction;
    /** @deprecated */ fastcall(definition: string): KoffiFunction;
    /** @deprecated */ fastcall(name: string | number, result: TypeSpec, arguments: TypeSpec[]): KoffiFunction;
    /** @deprecated */ thiscall(definition: string): KoffiFunction;
    /** @deprecated */ thiscall(name: string | number, result: TypeSpec, arguments: TypeSpec[]): KoffiFunction;
    symbol(name: string, type: TypeSpec): any;
    unload(): void;
}
export function struct(name: string | null | undefined, def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
export function struct(ref: IKoffiCType, def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
export function struct(def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
export function pack(name: string | null | undefined, def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
export function pack(ref: IKoffiCType, def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
export function pack(def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
export function union(name: string | null | undefined, def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
export function union(ref: IKoffiCType, def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
export function union(def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
export class Union {
    constructor(type: TypeSpec);
    [s: string]: any;
}
export function array(ref: TypeSpec, len: number, hint?: ArrayHint | null): IKoffiCType;
export function array(ref: TypeSpec, countedBy: string, maxLen: number, hint?: ArrayHint | null): IKoffiCType;
export function opaque(name: string | null | undefined): IKoffiCType;
export function opaque(): IKoffiCType;
/** @deprecated */ export function handle(name: string | null | undefined): IKoffiCType;
/** @deprecated */ export function handle(): IKoffiCType;
export function pointer(ref: TypeSpec): IKoffiCType;
export function pointer(ref: TypeSpec, count: number): IKoffiCType;
export function pointer(name: string | null | undefined, ref: TypeSpec, countedBy?: string | null): IKoffiCType;
export function pointer(name: string | null | undefined, ref: TypeSpec, count: number): IKoffiCType;
export function out(type: TypeSpec): IKoffiCType;
export function inout(type: TypeSpec): IKoffiCType;
export function disposable(type: TypeSpec): IKoffiCType;
export function disposable(type: TypeSpec, freeFunction: Function): IKoffiCType;
export function disposable(name: string | null | undefined, type: TypeSpec): IKoffiCType;
export function disposable(name: string | null | undefined, type: TypeSpec, freeFunction: Function): IKoffiCType;
export function proto(definition: string): IKoffiCType;
export function proto(result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
export function proto(convention: string, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
export function proto(name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
export function proto(convention: string, name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
/** @deprecated */ export function callback(definition: string): IKoffiCType;
/** @deprecated */ export function callback(result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
/** @deprecated */ export function callback(convention: string, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
/** @deprecated */ export function callback(name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
/** @deprecated */ export function callback(convention: string, name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
export function register(callback: Function, type: TypeSpec): IKoffiRegisteredCallback;
export function register(thisValue: any, callback: Function, type: TypeSpec): IKoffiRegisteredCallback;
export function unregister(callback: IKoffiRegisteredCallback): void;
export function as(value: any, type: TypeSpec): IKoffiPointerCast;
export function decode(value: any, type: TypeSpec): any;
export function decode(value: any, type: TypeSpec, len: number): any;
export function decode(value: any, offset: number, type: TypeSpec): any;
export function decode(value: any, offset: number, type: TypeSpec, len: number): any;
export function address(value: any): bigint;
export function call(value: any, type: TypeSpec, ...args: any[]): any;
export function encode(ref: any, type: TypeSpec, value: any): void;
export function encode(ref: any, type: TypeSpec, value: any, len: number): void;
export function encode(ref: any, offset: number, type: TypeSpec): void;
export function encode(ref: any, offset: number, type: TypeSpec, value: any): void;
export function encode(ref: any, offset: number, type: TypeSpec, value: any, len: number): void;
export function view(ref: any, len: number): ArrayBuffer;
export function sizeof(type: TypeSpec): number;
export function alignof(type: TypeSpec): number;
export function offsetof(type: TypeSpec, member_name: string): number;
export function resolve(type: TypeSpec): IKoffiCType;
export function introspect(type: TypeSpec): TypeInfo;
export function alias(name: string, type: TypeSpec): IKoffiCType;
type KoffiConfig = {
    sync_stack_size: number
    sync_heap_size: number
    async_stack_size: number
    async_heap_size: number
    resident_async_pools: number
    max_async_calls: number
    max_type_size: number
};
type KoffiStats = {
    disposed: number
};
export function config(): KoffiConfig;
export function config(cfg: KoffiConfig): KoffiConfig;
export function stats(): KoffiStats;
export function alloc(type: TypeSpec, length: number): any;
export function free(value: any): void;
export function errno(): number;
export function errno(value: number): number;
export function reset(): void;
export const internal: Boolean;
export const extension: String;
export const os: {
    errno: Record<string, number>
};
// https://koffi.dev/input#standard-types
type PrimitiveTypes =
    | 'bool'
    | 'char'
    | 'char16_t'
    | 'char16'
    | 'char32_t'
    | 'char32'
    | 'double'
    | 'float'
    | 'float32'
    | 'float64'
    | 'int'
    | 'int8_t'
    | 'int8'
    | 'int16_be_t'
    | 'int16_be'
    | 'int16_le_t'
    | 'int16_le'
    | 'int16_t'
    | 'int16'
    | 'int32_be_t'
    | 'int32_be'
    | 'int32_le_t'
    | 'int32_le'
    | 'int32_t'
    | 'int32'
    | 'int64_be_t'
    | 'int64_be'
    | 'int64_le_t'
    | 'int64_le'
    | 'int64_t'
    | 'int64'
    | 'intptr_t'
    | 'intptr'
    | 'long long'
    | 'long'
    | 'longlong'
    | 'short'
    | 'size_t'
    | 'str'
    | 'str16'
    | 'str32'
    | 'string'
    | 'string16'
    | 'string32'
    | 'uchar'
    | 'uint'
    | 'uint8_t'
    | 'uint8'
    | 'uint16_be_t'
    | 'uint16_be'
    | 'uint16_le_t'
    | 'uint16_le'
    | 'uint16_t'
    | 'uint16'
    | 'uint32_be_t'
    | 'uint32_be'
    | 'uint32_le_t'
    | 'uint32_le'
    | 'uint32_t'
    | 'uint32'
    | 'uint64_be_t'
    | 'uint64_be'
    | 'uint64_le_t'
    | 'uint64_le'
    | 'uint64_t'
    | 'uint64'
    | 'uintptr_t'
    | 'uintptr'
    | 'ulong'
    | 'ulonglong'
    | 'unsigned char'
    | 'unsigned int'
    | 'unsigned long long'
    | 'unsigned long'
    | 'unsigned short'
    | 'ushort'
    | 'void'
    | 'wchar'
    | 'wchar_t';
export const types: Record<PrimitiveTypes, IKoffiCType>;
// Internal stuff, don't use!
export const node: {
    env: { __brand: 'IKoffiNodeEnv' }
};