@types/ffi-napi
Version:
TypeScript definitions for ffi-napi
539 lines (478 loc) • 22.5 kB
TypeScript
/// <reference types="node" />
import ref = require("ref-napi");
import ref_struct = require("ref-struct-di");
import StructType = ref_struct.StructType;
/**
* This is a marker type that causes TypeScript to use string literal inference when inferring a generic from an array of {@link ref.TypeLike}.
*/
export type ArgTypesInferenceMarker = ["void"];
export interface LibraryFunctionOptions {
abi?: number | undefined;
async?: boolean | undefined;
varargs?: boolean | undefined;
}
/**
* Base constraint for an object-based library type definition.
*/
export type LibraryObjectDefinitionBase = Record<
string,
[retType: ref.TypeLike, argTypes: ref.TypeLike[], opts?: LibraryFunctionOptions]
>;
/**
* This is a marker type that causes TypeScript to use string literal inference when inferring a generic from {@link LibraryObjectDefinitionBase}.
* If it is not used, `new Library(..., { x: ["int", ["int"]] })` will be inferred as `new Library<{ x: [string, string[]] }>(...)` instead of `new UnionType<{ x: ["int", ["int"]] }>(...)`.
*/
export type LibraryObjectDefinitionInferenceMarker = Record<
string,
[retType: "void", argTypes: ArgTypesInferenceMarker]
>;
/**
* Converts a {@link LibraryObjectDefinitionBase} into a consistent subtype of {@link LibraryDefinitionBase}. If `any` is used, it is passed along
* to be interpreted to use a fallback definition for a union.
*/
export type LibraryObjectDefinitionToLibraryDefinition<T extends LibraryObjectDefinitionBase> = [T] extends
[never] | [0] ? any // catches T extends never/any (since `0` doesn't overlap with our constraint)
: { [P in keyof T]: [retType: ref.CoerceType<T[P][0]>, argTypes: ref.CoerceTypes<T[P][1]>, opts: T[P][2]] };
/**
* Base constraint for a consistent library type definition.
*/
export type LibraryDefinitionBase = Record<
string,
[retType: ref.Type, argTypes: ref.Type[], opts: LibraryFunctionOptions | undefined]
>;
/**
* Represents a {@link Library} instance created from a {@link LibraryDefinitionBase}.
*/
export type LibraryObject<T extends LibraryDefinitionBase> = [T] extends [never] | [0] ? any // catches T extends never/any (since `0` doesn't overlap with our constraint)
: {
[P in keyof T]: T[P][2] extends undefined
? ForeignFunction<ref.UnderlyingType<T[P][0]>, ref.UnderlyingTypes<T[P][1]>>
: T[P][2] extends { varargs: true } ? VariadicForeignFunction<T[P][0], T[P][1]>
: T[P][2] extends { async: true }
? ForeignFunction<ref.UnderlyingType<T[P][0]>, ref.UnderlyingTypes<T[P][1]>>["async"]
: ForeignFunction<ref.UnderlyingType<T[P][0]>, ref.UnderlyingTypes<T[P][1]>>;
};
/** Provides a friendly API on-top of `DynamicLibrary` and `ForeignFunction`. */
export interface Library {
/** The extension to use on libraries. */
EXT: string;
/**
* @param libFile name of library
* @param funcs hash of [retType, [...argType], opts?: {abi?, async?, varargs?}]
* @param lib hash that will be extended
*/
new<TDefinition extends LibraryObjectDefinitionBase | LibraryObjectDefinitionInferenceMarker, T>(
libFile: string | null,
funcs: TDefinition,
lib: T,
): T & LibraryObject<LibraryObjectDefinitionToLibraryDefinition<TDefinition>>;
/**
* @param libFile name of library
* @param funcs hash of [retType, [...argType], opts?: {abi?, async?, varargs?}]
* @param lib hash that will be extended
*/
new<TDefinition extends LibraryObjectDefinitionBase | LibraryObjectDefinitionInferenceMarker>(
libFile: string | null,
funcs: TDefinition,
lib?: object,
): LibraryObject<LibraryObjectDefinitionToLibraryDefinition<TDefinition>>;
/**
* @param libFile name of library
* @param funcs hash of [retType, [...argType], opts?: {abi?, async?, varargs?}]
* @param lib hash that will be extended
*/
new(
libFile: string | null,
funcs?: Record<string, [retType: ref.TypeLike, argTypes: ref.TypeLike[], opts?: LibraryFunctionOptions]>,
lib?: object,
): any;
/**
* @param libFile name of library
* @param funcs hash of [retType, [...argType], opts?: {abi?, async?, varargs?}]
* @param lib hash that will be extended
*/
<TDefinition extends LibraryObjectDefinitionBase | LibraryObjectDefinitionInferenceMarker, T>(
libFile: string | null,
funcs: TDefinition,
lib: T,
): T & LibraryObject<LibraryObjectDefinitionToLibraryDefinition<TDefinition>>;
/**
* @param libFile name of library
* @param funcs hash of [retType, [...argType], opts?: {abi?, async?, varargs?}]
* @param lib hash that will be extended
*/
<TDefinition extends LibraryObjectDefinitionBase | LibraryObjectDefinitionInferenceMarker>(
libFile: string | null,
funcs: TDefinition,
lib?: object,
): LibraryObject<LibraryObjectDefinitionToLibraryDefinition<TDefinition>>;
/**
* @param libFile name of library
* @param funcs hash of [retType, [...argType], opts?: {abi?, async?, varargs?}]
* @param lib hash that will be extended
*/
(
libFile: string | null,
funcs?: Record<string, [retType: ref.TypeLike, argTypes: ref.TypeLike[], opts?: LibraryFunctionOptions]>,
lib?: object,
): any;
}
export const Library: Library;
/** Get value of errno. */
export function errno(): number;
export interface Function<
TReturnType extends ref.Type = ref.Type,
TArgTypes extends ref.Type[] = ref.Type[],
> extends ref.Type<(...args: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>> {
/** The type of return value. */
retType: TReturnType;
/** The type of arguments. */
argTypes: TArgTypes;
/** Is set for node-ffi functions. */
ffi_type: PFFI_TYPE;
abi: number;
/** Get a `Callback` pointer of this function type. */
toPointer(
fn: (...args: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>,
): ref.Pointer<(...args: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>>;
/** Get a `ForeignFunction` of this function type. */
toFunction(buf: Buffer): ForeignFunction<ref.UnderlyingType<TReturnType>, ref.UnderlyingTypes<TArgTypes>>;
}
/** Creates and returns a type for a C function pointer. */
export const Function: {
// NOTE: This overload is a subtype of the next overload, but provides better completions.
new<TReturnType extends ref.NamedTypeLike, TArgTypes extends ref.NamedTypeLike[] | ArgTypesInferenceMarker>(
retType: TReturnType,
argTypes: TArgTypes,
abi?: number,
): Function<ref.CoerceType<TReturnType>, ref.CoerceTypes<TArgTypes>>;
new<TReturnType extends ref.TypeLike, TArgTypes extends ref.TypeLike[] | ArgTypesInferenceMarker>(
retType: TReturnType,
argTypes: TArgTypes,
abi?: number,
): Function<ref.CoerceType<TReturnType>, ref.CoerceTypes<TArgTypes>>;
new(retType: ref.TypeLike, argTypes: ref.TypeLike[], abi?: number): Function;
// NOTE: This overload is a subtype of the next overload, but provides better completions.
<TReturnType extends ref.NamedTypeLike, TArgTypes extends ref.NamedTypeLike[] | ArgTypesInferenceMarker>(
retType: TReturnType,
argTypes: TArgTypes,
abi?: number,
): Function<ref.CoerceType<TReturnType>, ref.CoerceTypes<TArgTypes>>;
<TReturnType extends ref.TypeLike, TArgTypes extends ref.Type[] | ArgTypesInferenceMarker>(
retType: TReturnType,
argTypes: TArgTypes,
abi?: number,
): Function<ref.CoerceType<TReturnType>, ref.CoerceTypes<TArgTypes>>;
(retType: ref.TypeLike, argTypes: ref.TypeLike[], abi?: number): Function;
};
export interface ForeignFunction<TReturn = any, TArgs extends any[] = any[]> {
(...args: TArgs): TReturn;
async(...args: [...TArgs, (err: any, value: TReturn) => void]): void;
}
/**
* Represents a foreign function in another library. Manages all of the aspects
* of function execution, including marshalling the data parameters for the
* function into native types and also unmarshalling the return from function
* execution.
*/
export const ForeignFunction: {
// NOTE: This overload is a subtype of the next overload, but provides better completions.
new<TReturnType extends ref.NamedType, TArgTypes extends ref.TypeLike[] | ArgTypesInferenceMarker>(
ptr: Buffer,
retType: TReturnType,
argTypes: TArgTypes,
abi?: number,
): ForeignFunction<ref.UnderlyingType<TReturnType>, ref.UnderlyingTypes<TArgTypes>>;
new<TReturnType extends ref.TypeLike, TArgTypes extends ref.TypeLike[] | ArgTypesInferenceMarker>(
ptr: Buffer,
retType: TReturnType,
argTypes: TArgTypes,
abi?: number,
): ForeignFunction<ref.UnderlyingType<TReturnType>, ref.UnderlyingTypes<TArgTypes>>;
new(ptr: Buffer, retType: ref.TypeLike, argTypes: ref.TypeLike[], abi?: number): ForeignFunction;
// NOTE: This overload is a subtype of the next overload, but provides better completions.
<TReturnType extends ref.NamedType, TArgTypes extends ref.TypeLike[] | ArgTypesInferenceMarker>(
ptr: Buffer,
retType: TReturnType,
argTypes: TArgTypes,
abi?: number,
): ForeignFunction<ref.UnderlyingType<TReturnType>, ref.UnderlyingTypes<TArgTypes>>;
<TReturnType extends ref.TypeLike, TArgTypes extends ref.TypeLike[] | ArgTypesInferenceMarker>(
ptr: Buffer,
retType: TReturnType,
argTypes: TArgTypes,
abi?: number,
): ForeignFunction<ref.UnderlyingType<TReturnType>, ref.UnderlyingTypes<TArgTypes>>;
(ptr: Buffer, retType: ref.TypeLike, argTypes: ref.TypeLike[], abi?: number): ForeignFunction;
};
export interface VariadicForeignFunction<
TReturnType extends ref.Type = ref.Type,
TArgTypes extends ref.Type[] = ref.Type[],
> {
/**
* What gets returned is another function that needs to be invoked with the rest
* of the variadic types that are being invoked from the function.
*/
// NOTE: This overload is a subtype of the next overload, but provides better completions.
<A extends ref.NamedTypeLike[]>(
...args: A
): ForeignFunction<ref.UnderlyingType<TReturnType>, [...ref.UnderlyingTypes<TArgTypes>, ...ref.UnderlyingTypes<A>]>;
/**
* What gets returned is another function that needs to be invoked with the rest
* of the variadic types that are being invoked from the function.
*/
<A extends ref.TypeLike[]>(
...args: A
): ForeignFunction<ref.UnderlyingType<TReturnType>, [...ref.UnderlyingTypes<TArgTypes>, ...ref.UnderlyingTypes<A>]>;
/**
* Return type as a property of the function generator to
* allow for monkey patching the return value in the very rare case where the
* return type is variadic as well
*/
returnType: TReturnType;
}
/**
* For when you want to call to a C function with variable amount of arguments.
* i.e. `printf`.
*
* This function takes care of caching and reusing `ForeignFunction` instances that
* contain the same ffi_type argument signature.
*/
export const VariadicForeignFunction: {
// NOTE: This overload is a subtype of the next overload, but provides better completions.
new<TReturnType extends ref.NamedTypeLike, TArgTypes extends ref.NamedTypeLike[] | ArgTypesInferenceMarker>(
ptr: Buffer,
ret: TReturnType,
fixedArgs: TArgTypes,
abi?: number,
): VariadicForeignFunction<ref.CoerceType<TReturnType>, ref.CoerceTypes<TArgTypes>>;
new<TReturnType extends ref.TypeLike, TArgTypes extends ref.TypeLike[] | ArgTypesInferenceMarker>(
ptr: Buffer,
ret: TReturnType,
fixedArgs: TArgTypes,
abi?: number,
): VariadicForeignFunction<ref.CoerceType<TReturnType>, ref.CoerceTypes<TArgTypes>>;
new(ptr: Buffer, ret: ref.TypeLike, fixedArgs: ref.TypeLike[], abi?: number): VariadicForeignFunction;
// NOTE: This overload is a subtype of the next overload, but provides better completions.
<TReturnType extends ref.NamedTypeLike, TArgTypes extends ref.NamedTypeLike[] | ArgTypesInferenceMarker>(
ptr: Buffer,
ret: TReturnType,
fixedArgs: TArgTypes,
abi?: number,
): VariadicForeignFunction<ref.CoerceType<TReturnType>, ref.CoerceTypes<TArgTypes>>;
<TReturnType extends ref.TypeLike, TArgTypes extends ref.TypeLike[] | ArgTypesInferenceMarker>(
ptr: Buffer,
ret: TReturnType,
fixedArgs: TArgTypes,
abi?: number,
): VariadicForeignFunction<ref.CoerceType<TReturnType>, ref.CoerceTypes<TArgTypes>>;
(ptr: Buffer, ret: ref.TypeLike, fixedArgs: ref.TypeLike[], abi?: number): VariadicForeignFunction;
};
/**
* This class loads and fetches function pointers for dynamic libraries
* (`.so`, `.dylib`, `etc`). After the libray's function pointer is acquired, then you
* call {@link DynamicLibrary.get} to retreive a pointer to an exported symbol. You need to
* call `get___` on the pointer to dereference it into its actual value, or
* turn the pointer into a callable function with {@link ForeignFunction}.
*/
export class DynamicLibrary {
/**
* @param mode One of the numeric {@link DynamicLibrary.FLAGS} values.
*/
constructor(path?: string, mode?: number);
/**
* Close library, returns the result of the `dlclose` system function.
*/
close(): number;
/**
* Get a symbol from this library.
*/
get(symbol: string): Buffer;
/**
* Get the result of the `dlerror` system function.
*/
error(): string;
/**
* Returns the path originally passed to the constructor.
*/
path(): string;
}
/**
* This class loads and fetches function pointers for dynamic libraries
* (`.so`, `.dylib`, etc). After the libray's function pointer is acquired, then you
* call {@link DynamicLibrary.get} to retreive a pointer to an exported symbol. You need to
* call `get___` on the pointer to dereference it into its actual value, or
* turn the pointer into a callable function with {@link ForeignFunction}.
*
* @param mode One of the numeric {@link DynamicLibrary.FLAGS} values.
*/
export function DynamicLibrary(path?: string, mode?: number): DynamicLibrary;
export namespace DynamicLibrary {
/**
* Exported flags from "dlfcn.h"
*/
namespace FLAGS {
// flags for dlopen()
const RTLD_LAZY: number;
const RTLD_NOW: number;
const RTLD_LOCAL: number;
const RTLD_GLOBAL: number;
const RTLD_NOLOAD: number | undefined; // not defined on Windows
const RTLD_NODELETE: number | undefined; // not defined on Windows
const RTLD_FIRST: number | undefined; // not defined on Windows
// flags for dlsym()
const RTLD_NEXT: ref.Pointer<unknown>;
const RTLD_DEFAULT: ref.Pointer<unknown>;
const RTLD_SELF: ref.Pointer<unknown> | undefined; // not defined on Windows
const RTLD_MAIN_ONLY: ref.Pointer<unknown> | undefined; // not defined on Windows
}
}
/**
* Turns a JavaScript function into a C function pointer.
* The function pointer may be used in other C functions that
* accept C callback functions.
*/
export interface Callback {
// NOTE: This overload is a subtype of the next overload, but provides better completions.
new<TReturnType extends ref.NamedTypeLike, TArgTypes extends ref.NamedTypeLike[]>(
retType: TReturnType,
argTypes: TArgTypes,
abi: number,
fn: (...args: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>,
): ref.Pointer<(...args: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>>;
new<TReturnType extends ref.TypeLike, TArgTypes extends ref.TypeLike[]>(
retType: TReturnType,
argTypes: TArgTypes,
abi: number,
fn: (...args: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>,
): ref.Pointer<(...args: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>>;
// NOTE: This overload is a subtype of the next overload, but provides better completions.
new<TReturnType extends ref.NamedTypeLike, TArgTypes extends ref.NamedTypeLike[]>(
retType: TReturnType,
argTypes: TArgTypes,
fn: (...ags: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>,
): ref.Pointer<(...args: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>>;
new<TReturnType extends ref.TypeLike, TArgTypes extends ref.TypeLike[]>(
retType: TReturnType,
argTypes: TArgTypes,
fn: (...ags: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>,
): ref.Pointer<(...args: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>>;
new(retType: ref.TypeLike, argTypes: ref.TypeLike[], abi: number, fn: (...args: any[]) => any): Buffer;
new(retType: ref.TypeLike, argTypes: ref.TypeLike[], fn: (...args: any[]) => any): Buffer;
// NOTE: This overload is a subtype of the next overload, but provides better completions.
<TReturnType extends ref.NamedTypeLike, TArgTypes extends ref.NamedTypeLike[]>(
retType: TReturnType,
argTypes: TArgTypes,
abi: number,
fn: (...args: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>,
): ref.Pointer<(...args: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>>;
<TReturnType extends ref.TypeLike, TArgTypes extends ref.TypeLike[]>(
retType: TReturnType,
argTypes: TArgTypes,
abi: number,
fn: (...args: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>,
): ref.Pointer<(...args: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>>;
// NOTE: This overload is a subtype of the next overload, but provides better completions.
<TReturnType extends ref.NamedTypeLike, TArgTypes extends ref.NamedTypeLike[]>(
retType: TReturnType,
argTypes: TArgTypes,
fn: (...ags: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>,
): ref.Pointer<(...args: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>>;
<TReturnType extends ref.TypeLike, TArgTypes extends ref.TypeLike[]>(
retType: TReturnType,
argTypes: TArgTypes,
fn: (...ags: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>,
): ref.Pointer<(...args: ref.UnderlyingTypes<TArgTypes>) => ref.UnderlyingType<TReturnType>>;
(retType: ref.TypeLike, argTypes: ref.TypeLike[], abi: number, fn: (...args: any[]) => any): Buffer;
(retType: ref.TypeLike, argTypes: ref.TypeLike[], fn: (...args: any[]) => any): Buffer;
}
export const Callback: Callback;
/** Get a `ffi_type *` Buffer appropriate for the given type. */
export function ffiType(type: ref.TypeLike): ref.Pointer<FFI_TYPE>;
export namespace ffiType {
/**
* Define the `ffi_type` struct (see deps/libffi/include/ffi.h) for use in JS.
* This struct type is used internally to define custom struct ret/arg types.
*/
const FFI_TYPE: StructType<{
size: typeof ref.types.size_t;
alignment: typeof ref.types.ushort;
type: typeof ref.types.ushort;
elements: ref.Type<ref.Pointer<PFFI_TYPE>>;
}>;
type FFI_TYPE = ReturnType<typeof FFI_TYPE>;
}
export function CIF(retType: ref.TypeLike, types: ref.TypeLike[], abi?: number): Buffer;
export function CIF_var(retType: ref.TypeLike, types: ref.TypeLike[], numFixedArgs: number, abi?: number): Buffer;
export const HAS_OBJC: boolean;
/**
* Represents an opaque pointer to an {@link FFI_TYPE} struct used for marshalling types to native code.
*/
export type PFFI_TYPE = ref.Pointer<FFI_TYPE>;
declare module "ref-napi" {
interface Type {
/**
* Determines the FFI_TYPE set for a type.
*/
ffi_type?: PFFI_TYPE | undefined;
}
}
export interface FfiTypesRegistry {
void: PFFI_TYPE;
uint8: PFFI_TYPE;
int8: PFFI_TYPE;
uint16: PFFI_TYPE;
int16: PFFI_TYPE;
uint32: PFFI_TYPE;
int32: PFFI_TYPE;
uint64: PFFI_TYPE;
int64: PFFI_TYPE;
uchar: PFFI_TYPE;
char: PFFI_TYPE;
ushort: PFFI_TYPE;
short: PFFI_TYPE;
uint: PFFI_TYPE;
int: PFFI_TYPE;
float: PFFI_TYPE;
double: PFFI_TYPE;
pointer: PFFI_TYPE;
ulonglong: PFFI_TYPE;
longlong: PFFI_TYPE;
ulong: PFFI_TYPE;
long: PFFI_TYPE;
}
export const FFI_TYPES: FfiTypesRegistry;
export const FFI_OK: number;
export const FFI_BAD_TYPEDEF: number;
export const FFI_BAD_ABI: number;
export const FFI_DEFAULT_ABI: number;
export const FFI_FIRST_ABI: number;
export const FFI_LAST_ABI: number;
// NOTE: These are defined depending on the platform ffi-napi was compiled on:
export const FFI_SYSV: number | undefined; // __arm__, Intel x86 Win32, __aarch64__, Intel x86 and AMD x86/x64
export const FFI_VFP: number | undefined; // __arm__
export const FFI_UNIX64: number | undefined; // All unix variants
export const FFI_STDCALL: number | undefined; // Intel x86 Win32
export const FFI_THISCALL: number | undefined; // Intel x86 Win32
export const FFI_FASTCALL: number | undefined; // Intel x86 Win32
export const FFI_MS_CDECL: number | undefined; // Intel x86 Win32
export const FFI_WIN64: number | undefined; // Intel x86 Win64
export import RTLD_LAZY = DynamicLibrary.FLAGS.RTLD_LAZY;
export import RTLD_NOW = DynamicLibrary.FLAGS.RTLD_NOW;
export import RTLD_LOCAL = DynamicLibrary.FLAGS.RTLD_LOCAL;
export import RTLD_GLOBAL = DynamicLibrary.FLAGS.RTLD_GLOBAL;
export import RTLD_NOLOAD = DynamicLibrary.FLAGS.RTLD_NOLOAD;
export import RTLD_NODELETE = DynamicLibrary.FLAGS.RTLD_NODELETE;
export import RTLD_FIRST = DynamicLibrary.FLAGS.RTLD_FIRST;
export import RTLD_NEXT = DynamicLibrary.FLAGS.RTLD_NEXT;
export import RTLD_DEFAULT = DynamicLibrary.FLAGS.RTLD_DEFAULT;
export import RTLD_SELF = DynamicLibrary.FLAGS.RTLD_SELF;
export import RTLD_MAIN_ONLY = DynamicLibrary.FLAGS.RTLD_MAIN_ONLY;
export const FFI_ARG_SIZE: number;
export const FFI_SARG_SIZE: number;
export const FFI_TYPE_SIZE: number;
export const FFI_CIF_SIZE: number;
export const LIB_EXT: string;
export import FFI_TYPE = ffiType.FFI_TYPE;
/** Default types. */
export import types = ref.types;