/** * `bun:ffi` lets you efficiently call C functions & FFI functions from JavaScript * without writing bindings yourself. * * ```js * import {dlopen, CString, ptr} from 'bun:ffi'; * * const lib = dlopen('libsqlite3', { * }); * ``` * * This is powered by just-in-time compiling C wrappers * that convert JavaScript types to C types and back. Internally, * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks * goes to Fabrice Bellard and TinyCC maintainers for making this possible. * */ declare module "bun:ffi" { export enum FFIType { char = 0, /** * 8-bit signed integer * * Must be a value between -127 and 127 * * When passing to a FFI function (C ABI), type coercion is not performed. * * In C: * ```c * signed char * char // on x64 & aarch64 macOS * ``` * * In JavaScript: * ```js * var num = 0; * ``` */ int8_t = 1, /** * 8-bit signed integer * * Must be a value between -127 and 127 * * When passing to a FFI function (C ABI), type coercion is not performed. * * In C: * ```c * signed char * char // on x64 & aarch64 macOS * ``` * * In JavaScript: * ```js * var num = 0; * ``` */ i8 = 1, /** * 8-bit unsigned integer * * Must be a value between 0 and 255 * * When passing to a FFI function (C ABI), type coercion is not performed. * * In C: * ```c * unsigned char * ``` * * In JavaScript: * ```js * var num = 0; * ``` */ uint8_t = 2, /** * 8-bit unsigned integer * * Must be a value between 0 and 255 * * When passing to a FFI function (C ABI), type coercion is not performed. * * In C: * ```c * unsigned char * ``` * * In JavaScript: * ```js * var num = 0; * ``` */ u8 = 2, /** * 16-bit signed integer * * Must be a value between -32768 and 32767 * * When passing to a FFI function (C ABI), type coercion is not performed. * * In C: * ```c * in16_t * short // on arm64 & x64 * ``` * * In JavaScript: * ```js * var num = 0; * ``` */ int16_t = 3, /** * 16-bit signed integer * * Must be a value between -32768 and 32767 * * When passing to a FFI function (C ABI), type coercion is not performed. * * In C: * ```c * in16_t * short // on arm64 & x64 * ``` * * In JavaScript: * ```js * var num = 0; * ``` */ i16 = 3, /** * 16-bit unsigned integer * * Must be a value between 0 and 65535, inclusive. * * When passing to a FFI function (C ABI), type coercion is not performed. * * In C: * ```c * uint16_t * unsigned short // on arm64 & x64 * ``` * * In JavaScript: * ```js * var num = 0; * ``` */ uint16_t = 4, /** * 16-bit unsigned integer * * Must be a value between 0 and 65535, inclusive. * * When passing to a FFI function (C ABI), type coercion is not performed. * * In C: * ```c * uint16_t * unsigned short // on arm64 & x64 * ``` * * In JavaScript: * ```js * var num = 0; * ``` */ u16 = 4, /** * 32-bit signed integer * */ int32_t = 5, /** * 32-bit signed integer * * Alias of {@link FFIType.int32_t} */ i32 = 5, /** * 32-bit signed integer * * The same as `int` in C * * ```c * int * ``` */ int = 5, /** * 32-bit unsigned integer * * The same as `unsigned int` in C (on x64 & arm64) * * C: * ```c * unsigned int * ``` * JavaScript: * ```js * ptr(new Uint32Array(1)) * ``` */ uint32_t = 6, /** * 32-bit unsigned integer * * Alias of {@link FFIType.uint32_t} */ u32 = 6, /** * int64 is a 64-bit signed integer * * This is not implemented yet! */ int64_t = 7, /** * i64 is a 64-bit signed integer * * This is not implemented yet! */ i64 = 7, /** * 64-bit unsigned integer * * This is not implemented yet! */ uint64_t = 8, /** * 64-bit unsigned integer * * This is not implemented yet! */ u64 = 8, /** * Doubles are not supported yet! */ double = 9, /** * Doubles are not supported yet! */ f64 = 9, /** * Floats are not supported yet! */ float = 10, /** * Floats are not supported yet! */ f32 = 10, /** * Booelan value * * Must be `true` or `false`. `0` and `1` type coercion is not supported. * * In C, this corresponds to: * ```c * bool * _Bool * ``` * * */ bool = 11, /** * Pointer value * * See {@link Bun.FFI.ptr} for more information * * In C: * ```c * void* * ``` * * In JavaScript: * ```js * ptr(new Uint8Array(1)) * ``` */ ptr = 12, /** * Pointer value * * alias of {@link FFIType.ptr} */ pointer = 12, /** * void value * * void arguments are not supported * * void return type is the default return type * * In C: * ```c * void * ``` * */ void = 13, /** * When used as a `returns`, this will automatically become a {@link CString}. * * When used in `args` it is equivalent to {@link FFIType.pointer} * */ cstring = 14, /** * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance * but means you might get a `BigInt` or you might get a `number`. * * In C, this always becomes `int64_t` * * In JavaScript, this could be number or it could be BigInt, depending on what * value is passed in. * */ i64_fast = 15, /** * Attempt to coerce `BigInt` into a `Number` if it fits. This improves performance * but means you might get a `BigInt` or you might get a `number`. * * In C, this always becomes `uint64_t` * * In JavaScript, this could be number or it could be BigInt, depending on what * value is passed in. * */ u64_fast = 16, function = 17, } type UNTYPED = never; export type Pointer = number & {}; interface FFITypeToArgsType { [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]: number | bigint; [FFIType.i64]: number | bigint; [FFIType.uint64_t]: number | bigint; [FFIType.u64]: number | bigint; [FFIType.double]: number; [FFIType.f64]: number; [FFIType.float]: number; [FFIType.f32]: number; [FFIType.bool]: boolean; [FFIType.ptr]: TypedArray | Pointer | CString | null; [FFIType.pointer]: TypedArray | Pointer | CString | null; [FFIType.void]: void; [FFIType.cstring]: TypedArray | Pointer | CString | null; [FFIType.i64_fast]: number | bigint; [FFIType.u64_fast]: number | bigint; [FFIType.function]: Pointer | JSCallback; // cannot be null } interface FFITypeToReturnsType { [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]: bigint; [FFIType.i64]: bigint; [FFIType.uint64_t]: bigint; [FFIType.u64]: bigint; [FFIType.double]: number; [FFIType.f64]: number; [FFIType.float]: number; [FFIType.f32]: number; [FFIType.bool]: boolean; [FFIType.ptr]: Pointer | null; [FFIType.pointer]: Pointer | null; [FFIType.void]: void; [FFIType.cstring]: CString; [FFIType.i64_fast]: number | bigint; [FFIType.u64_fast]: number | bigint; [FFIType.function]: Pointer | null; } interface FFITypeStringToType { ["char"]: FFIType.char; ["int8_t"]: FFIType.int8_t; ["i8"]: FFIType.i8; ["uint8_t"]: FFIType.uint8_t; ["u8"]: FFIType.u8; ["int16_t"]: FFIType.int16_t; ["i16"]: FFIType.i16; ["uint16_t"]: FFIType.uint16_t; ["u16"]: FFIType.u16; ["int32_t"]: FFIType.int32_t; ["i32"]: FFIType.i32; ["int"]: FFIType.int; ["uint32_t"]: FFIType.uint32_t; ["u32"]: FFIType.u32; ["int64_t"]: FFIType.int64_t; ["i64"]: FFIType.i64; ["uint64_t"]: FFIType.uint64_t; ["u64"]: FFIType.u64; ["double"]: FFIType.double; ["f64"]: FFIType.f64; ["float"]: FFIType.float; ["f32"]: FFIType.f32; ["bool"]: FFIType.bool; ["ptr"]: FFIType.ptr; ["pointer"]: FFIType.pointer; ["void"]: FFIType.void; ["cstring"]: FFIType.cstring; ["function"]: FFIType.pointer; // for now ["usize"]: FFIType.uint64_t; // for now ["callback"]: FFIType.pointer; // for now } export type FFITypeOrString = FFIType | keyof FFITypeStringToType; interface FFIFunction { /** * Arguments to a FFI function (C ABI) * * Defaults to an empty array, which means no arguments. * * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. * * @example * From JavaScript: * ```ts * import { dlopen, FFIType, suffix } from "bun:ffi" * * const lib = dlopen(`adder.${suffix}`, { * add: { * // FFIType can be used or you can pass string labels. * args: [FFIType.i32, "i32"], * returns: "i32", * }, * }) * lib.symbols.add(1, 2) * ``` * In C: * ```c * int add(int a, int b) { * return a + b; * } * ``` */ readonly args?: readonly FFITypeOrString[]; /** * Return type to a FFI function (C ABI) * * Defaults to {@link FFIType.void} * * To pass a pointer, use "ptr" or "pointer" as the type name. To get a pointer, see {@link ptr}. * * @example * From JavaScript: * ```ts * import { dlopen, CString } from "bun:ffi" * * const lib = dlopen('z', { * version: { * returns: "ptr", * } * }); * console.log(new CString(lib.symbols.version())); * ``` * In C: * ```c * char* version() * { * return "1.0.0"; * } * ``` */ readonly returns?: FFITypeOrString; /** * Function pointer to the native function * * If provided, instead of using dlsym() to lookup the function, Bun will use this instead. * This pointer should not be null (0). * * This is useful if the library has already been loaded * or if the module is also using Node-API. */ readonly ptr?: number | bigint; /** * Can C/FFI code call this function from a separate thread? * * Only supported with {@link JSCallback}. * * This does not make the function run in a separate thread. It is still up to the application/library * to run their code in a separate thread. * * By default, {@link JSCallback} calls are not thread-safe. Turning this on * incurs a small performance penalty for every function call. That small * performance penalty needs to be less than the performance gain from * running the function in a separate thread. * * @default false */ readonly threadsafe?: boolean; } type Symbols = Readonly>; // /** // * Compile a callback function // * // * Returns a function pointer // * // */ // export function callback(ffi: FFIFunction, cb: Function): number; export interface Library< Fns extends Readonly>>, > { symbols: ConvertFns; /** * `dlclose` the library, unloading the symbols and freeing allocated memory. * * Once called, the library is no longer usable. * * Calling a function from a library that has been closed is undefined behavior. */ close(): void; } type ToFFIType = T extends FFIType ? T : T extends string ? FFITypeStringToType[T] : never; type _Narrow = [U] extends [T] ? U : Extract; type Narrow = | _Narrow | _Narrow | _Narrow | _Narrow | _Narrow | _Narrow | _Narrow | (T extends object ? { [K in keyof T]: Narrow } : never) | Extract<{} | null | undefined, T>; type ConvertFns>> = { [K in keyof Fns]: ( ...args: Fns[K]["args"] extends infer A extends readonly FFITypeOrString[] ? { [L in keyof A]: FFITypeToArgsType[ToFFIType] } : [unknown] extends [Fns[K]["args"]] ? [] : never ) => [unknown] extends [Fns[K]["returns"]] ? void : FFITypeToReturnsType[ToFFIType>]; }; /** * Open a library using `"bun:ffi"` * * @param name The name of the library or file path. This will be passed to `dlopen()` * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} * * @example * * ```js * import {dlopen} from 'bun:ffi'; * * const lib = dlopen("duckdb.dylib", { * get_version: { * returns: "cstring", * args: [], * }, * }); * lib.symbols.get_version(); * // "1.0.0" * ``` * * This is powered by just-in-time compiling C wrappers * that convert JavaScript types to C types and back. Internally, * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks * goes to Fabrice Bellard and TinyCC maintainers for making this possible. * */ export function dlopen>>( name: string, symbols: Fns, ): Library; /** * Turn a native library's function pointer into a JavaScript function * * Libraries using Node-API & bun:ffi in the same module could use this to skip an extra dlopen() step. * * @param fn {@link FFIFunction} declaration. `ptr` is required * * @example * * ```js * import {CFunction} from 'bun:ffi'; * * const getVersion = new CFunction({ * returns: "cstring", * args: [], * ptr: myNativeLibraryGetVersion, * }); * getVersion(); * getVersion.close(); * ``` * * This is powered by just-in-time compiling C wrappers * that convert JavaScript types to C types and back. Internally, * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks * goes to Fabrice Bellard and TinyCC maintainers for making this possible. * */ export function CFunction( fn: FFIFunction & { ptr: Pointer }, ): CallableFunction & { /** * Free the memory allocated by the wrapping function */ close(): void; }; /** * Link a map of symbols to JavaScript functions * * This lets you use native libraries that were already loaded somehow. You usually will want {@link dlopen} instead. * * You could use this with Node-API to skip loading a second time. * * @param symbols Map of symbols to load where the key is the symbol name and the value is the {@link FFIFunction} * * @example * * ```js * import { linkSymbols } from "bun:ffi"; * * const [majorPtr, minorPtr, patchPtr] = getVersionPtrs(); * * const lib = linkSymbols({ * // Unlike with dlopen(), the names here can be whatever you want * getMajor: { * returns: "cstring", * args: [], * * // Since this doesn't use dlsym(), you have to provide a valid ptr * // That ptr could be a number or a bigint * // An invalid pointer will crash your program. * ptr: majorPtr, * }, * getMinor: { * returns: "cstring", * args: [], * ptr: minorPtr, * }, * getPatch: { * returns: "cstring", * args: [], * ptr: patchPtr, * }, * }); * * const [major, minor, patch] = [ * lib.symbols.getMajor(), * lib.symbols.getMinor(), * lib.symbols.getPatch(), * ]; * ``` * * This is powered by just-in-time compiling C wrappers * that convert JavaScript types to C types and back. Internally, * bun uses [tinycc](https://github.com/TinyCC/tinycc), so a big thanks * goes to Fabrice Bellard and TinyCC maintainers for making this possible. * */ export function linkSymbols>>( symbols: Fns, ): Library; /** * Read a pointer as a {@link Buffer} * * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. * * @param ptr The memory address to read * @param byteOffset bytes to skip before reading * @param byteLength bytes to read * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! * */ export function toBuffer( ptr: Pointer, byteOffset?: number, byteLength?: number, ): Buffer; /** * Read a pointer as an {@link ArrayBuffer} * * If `byteLength` is not provided, the pointer is assumed to be 0-terminated. * * @param ptr The memory address to read * @param byteOffset bytes to skip before reading * @param byteLength bytes to read * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! */ export function toArrayBuffer( ptr: Pointer, byteOffset?: number, byteLength?: number, ): ArrayBuffer; export namespace read { /** * The read function behaves similarly to DataView, * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. * * @param ptr The memory address to read * @param byteOffset bytes to skip before reading * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! */ export function u8(ptr: Pointer, byteOffset?: number): number; /** * The read function behaves similarly to DataView, * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. * * @param ptr The memory address to read * @param byteOffset bytes to skip before reading * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! */ export function i8(ptr: Pointer, byteOffset?: number): number; /** * The read function behaves similarly to DataView, * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. * * @param ptr The memory address to read * @param byteOffset bytes to skip before reading * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! */ export function u16(ptr: Pointer, byteOffset?: number): number; /** * The read function behaves similarly to DataView, * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. * * @param ptr The memory address to read * @param byteOffset bytes to skip before reading * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! */ export function i16(ptr: Pointer, byteOffset?: number): number; /** * The read function behaves similarly to DataView, * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. * * @param ptr The memory address to read * @param byteOffset bytes to skip before reading * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! */ export function u32(ptr: Pointer, byteOffset?: number): number; /** * The read function behaves similarly to DataView, * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. * * @param ptr The memory address to read * @param byteOffset bytes to skip before reading * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! */ export function i32(ptr: Pointer, byteOffset?: number): number; /** * The read function behaves similarly to DataView, * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. * * @param ptr The memory address to read * @param byteOffset bytes to skip before reading * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! */ export function f32(ptr: Pointer, byteOffset?: number): number; /** * The read function behaves similarly to DataView, * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. * * @param ptr The memory address to read * @param byteOffset bytes to skip before reading * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! */ export function u64(ptr: Pointer, byteOffset?: number): bigint; /** * The read function behaves similarly to DataView, * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. * * @param ptr The memory address to read * @param byteOffset bytes to skip before reading * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! */ export function i64(ptr: Pointer, byteOffset?: number): bigint; /** * The read function behaves similarly to DataView, * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. * * @param ptr The memory address to read * @param byteOffset bytes to skip before reading * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! */ export function f64(ptr: Pointer, byteOffset?: number): number; /** * The read function behaves similarly to DataView, * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. * * @param ptr The memory address to read * @param byteOffset bytes to skip before reading * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! */ export function ptr(ptr: Pointer, byteOffset?: number): number; /** * The read function behaves similarly to DataView, * but it's usually faster because it doesn't need to create a DataView or ArrayBuffer. * * @param ptr The memory address to read * @param byteOffset bytes to skip before reading * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! */ export function intptr(ptr: Pointer, byteOffset?: number): number; } /** * Get the pointer backing a {@link TypedArray} or {@link ArrayBuffer} * * Use this to pass {@link TypedArray} or {@link ArrayBuffer} to C functions. * * This is for use with FFI functions. For performance reasons, FFI will * not automatically convert typed arrays to C pointers. * * @param {TypedArray|ArrayBuffer|DataView} view the typed array or array buffer to get the pointer for * @param {number} byteOffset optional offset into the view in bytes * * @example * * From JavaScript: * ```js * const array = new Uint8Array(10); * const rawPtr = ptr(array); * myFFIFunction(rawPtr); * ``` * To C: * ```c * void myFFIFunction(char* rawPtr) { * // Do something with rawPtr * } * ``` * */ export function ptr( view: TypedArray | ArrayBufferLike | DataView, byteOffset?: number, ): Pointer; /** * Get a string from a UTF-8 encoded C string * If `byteLength` is not provided, the string is assumed to be null-terminated. * * @example * ```js * var ptr = lib.symbols.getVersion(); * console.log(new CString(ptr)); * ``` * * @example * ```js * var ptr = lib.symbols.getVersion(); * // print the first 4 characters * console.log(new CString(ptr, 0, 4)); * ``` * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! */ export class CString extends String { /** * Get a string from a UTF-8 encoded C string * If `byteLength` is not provided, the string is assumed to be null-terminated. * * @param ptr The pointer to the C string * @param byteOffset bytes to skip before reading * @param byteLength bytes to read * * * @example * ```js * var ptr = lib.symbols.getVersion(); * console.log(new CString(ptr)); * ``` * * @example * ```js * var ptr = lib.symbols.getVersion(); * // print the first 4 characters * console.log(new CString(ptr, 0, 4)); * ``` * * While there are some checks to catch invalid pointers, this is a difficult * thing to do safely. Passing an invalid pointer can crash the program and * reading beyond the bounds of the pointer will crash the program or cause * undefined behavior. Use with care! */ constructor(ptr: Pointer, byteOffset?: number, byteLength?: number); /** * The ptr to the C string * * This `CString` instance is a clone of the string, so it * is safe to continue using this instance after the `ptr` has been * freed. */ ptr: Pointer; byteOffset?: number; byteLength?: number; /** * Get the {@link ptr} as an `ArrayBuffer` * * `null` or empty ptrs returns an `ArrayBuffer` with `byteLength` 0 */ get arrayBuffer(): ArrayBuffer; } /** * Pass a JavaScript function to FFI (Foreign Function Interface) */ export class JSCallback { /** * Enable a JavaScript callback function to be passed to C with bun:ffi * * @param callback The JavaScript function to be called * @param definition The C function definition */ constructor(callback: (...args: any[]) => any, definition: FFIFunction); /** * The pointer to the C function * * Becomes `null` once {@link JSCallback.prototype.close} is called */ readonly ptr: Pointer | null; /** * Can the callback be called from a different thread? */ readonly threadsafe: boolean; /** * Free the memory allocated for the callback * * If called multiple times, does nothing after the first call. */ close(): void; } /** * View the generated C code for FFI bindings * * You probably won't need this unless there's a bug in the FFI bindings * generator or you're just curious. */ export function viewSource(symbols: Symbols, is_callback?: false): string[]; export function viewSource(callback: FFIFunction, is_callback: true): string; /** * Platform-specific file extension name for dynamic libraries * * "." is not included * * @example * ```js * "dylib" // macOS * ``` * * @example * ```js * "so" // linux * ``` */ export const suffix: string; }