@lakutata/ffi 0.0.0-stage → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +163 -2
  3. package/README.zh-CN.md +140 -0
  4. package/dist/cjs/components/NativeLibrary.d.ts +229 -0
  5. package/dist/cjs/components/NativeLibrary.js +346 -0
  6. package/dist/cjs/decorators/Library.d.ts +61 -0
  7. package/dist/cjs/decorators/Library.js +44 -0
  8. package/dist/cjs/decorators/Native.d.ts +69 -0
  9. package/dist/cjs/decorators/Native.js +90 -0
  10. package/dist/cjs/exceptions/NativeDeclarationException.d.ts +12 -0
  11. package/dist/cjs/exceptions/NativeDeclarationException.js +19 -0
  12. package/dist/cjs/exceptions/NativeLibraryClosedException.d.ts +12 -0
  13. package/dist/cjs/exceptions/NativeLibraryClosedException.js +19 -0
  14. package/dist/cjs/exceptions/NativeLibraryNotFoundException.d.ts +11 -0
  15. package/dist/cjs/exceptions/NativeLibraryNotFoundException.js +18 -0
  16. package/dist/cjs/exceptions/NativeMemoryException.d.ts +11 -0
  17. package/dist/cjs/exceptions/NativeMemoryException.js +18 -0
  18. package/dist/cjs/exports/FFI.d.ts +12 -0
  19. package/dist/cjs/exports/FFI.js +40 -0
  20. package/dist/cjs/exports/Generator.d.ts +2 -0
  21. package/dist/cjs/exports/Generator.js +10 -0
  22. package/dist/cjs/lib/Memory.d.ts +188 -0
  23. package/dist/cjs/lib/Memory.js +227 -0
  24. package/dist/cjs/lib/Runtime.d.ts +98 -0
  25. package/dist/cjs/lib/Runtime.js +209 -0
  26. package/dist/cjs/lib/backend/Functions.d.ts +65 -0
  27. package/dist/cjs/lib/backend/Functions.js +214 -0
  28. package/dist/cjs/lib/backend/KoffiTypes.d.ts +53 -0
  29. package/dist/cjs/lib/backend/KoffiTypes.js +426 -0
  30. package/dist/cjs/lib/declarations/Builtins.d.ts +33 -0
  31. package/dist/cjs/lib/declarations/Builtins.js +179 -0
  32. package/dist/cjs/lib/declarations/Layout.d.ts +41 -0
  33. package/dist/cjs/lib/declarations/Layout.js +180 -0
  34. package/dist/cjs/lib/declarations/Lexer.d.ts +40 -0
  35. package/dist/cjs/lib/declarations/Lexer.js +325 -0
  36. package/dist/cjs/lib/declarations/Parser.d.ts +90 -0
  37. package/dist/cjs/lib/declarations/Parser.js +1425 -0
  38. package/dist/cjs/lib/declarations/Platform.d.ts +50 -0
  39. package/dist/cjs/lib/declarations/Platform.js +27 -0
  40. package/dist/cjs/lib/declarations/Types.d.ts +173 -0
  41. package/dist/cjs/lib/declarations/Types.js +179 -0
  42. package/dist/cjs/lib/generator/CText.d.ts +14 -0
  43. package/dist/cjs/lib/generator/CText.js +133 -0
  44. package/dist/cjs/lib/generator/Generator.d.ts +136 -0
  45. package/dist/cjs/lib/generator/Generator.js +395 -0
  46. package/dist/cjs/lib/generator/Preprocessor.d.ts +60 -0
  47. package/dist/cjs/lib/generator/Preprocessor.js +94 -0
  48. package/dist/cjs/lib/generator/TypeScriptTypes.d.ts +35 -0
  49. package/dist/cjs/lib/generator/TypeScriptTypes.js +153 -0
  50. package/dist/cjs/lib/library/NativeCallback.d.ts +44 -0
  51. package/dist/cjs/lib/library/NativeCallback.js +66 -0
  52. package/dist/cjs/lib/library/NativeLibraryHandle.d.ts +268 -0
  53. package/dist/cjs/lib/library/NativeLibraryHandle.js +540 -0
  54. package/dist/cjs/lib/library/Resolve.d.ts +49 -0
  55. package/dist/cjs/lib/library/Resolve.js +130 -0
  56. package/dist/cjs/lib/thread/NativeThreads.d.ts +80 -0
  57. package/dist/cjs/lib/thread/NativeThreads.js +384 -0
  58. package/dist/cjs/lib/thread/NativeWorker.d.ts +6 -0
  59. package/dist/cjs/lib/thread/NativeWorker.js +96 -0
  60. package/dist/cjs/lib/thread/NativeWorkerCode.d.ts +5 -0
  61. package/dist/cjs/lib/thread/NativeWorkerCode.js +4 -0
  62. package/dist/cjs/lib/thread/PackageRequire.d.ts +6 -0
  63. package/dist/cjs/lib/thread/PackageRequire.js +4 -0
  64. package/dist/cjs/lib/thread/ThreadProtocol.d.ts +77 -0
  65. package/dist/cjs/lib/thread/ThreadProtocol.js +2 -0
  66. package/dist/cjs/package.json +1 -0
  67. package/dist/esm/components/NativeLibrary.js +338 -0
  68. package/dist/esm/decorators/Library.js +40 -0
  69. package/dist/esm/decorators/Native.js +85 -0
  70. package/dist/esm/exceptions/NativeDeclarationException.js +15 -0
  71. package/dist/esm/exceptions/NativeLibraryClosedException.js +15 -0
  72. package/dist/esm/exceptions/NativeLibraryNotFoundException.js +14 -0
  73. package/dist/esm/exceptions/NativeMemoryException.js +14 -0
  74. package/dist/esm/exports/FFI.js +10 -0
  75. package/dist/esm/exports/Generator.js +2 -0
  76. package/dist/esm/lib/Memory.js +210 -0
  77. package/dist/esm/lib/Runtime.js +192 -0
  78. package/dist/esm/lib/backend/Functions.js +206 -0
  79. package/dist/esm/lib/backend/KoffiTypes.js +418 -0
  80. package/dist/esm/lib/declarations/Builtins.js +174 -0
  81. package/dist/esm/lib/declarations/Layout.js +175 -0
  82. package/dist/esm/lib/declarations/Lexer.js +321 -0
  83. package/dist/esm/lib/declarations/Parser.js +1421 -0
  84. package/dist/esm/lib/declarations/Platform.js +23 -0
  85. package/dist/esm/lib/declarations/Types.js +170 -0
  86. package/dist/esm/lib/generator/CText.js +129 -0
  87. package/dist/esm/lib/generator/Generator.js +388 -0
  88. package/dist/esm/lib/generator/Preprocessor.js +87 -0
  89. package/dist/esm/lib/generator/TypeScriptTypes.js +149 -0
  90. package/dist/esm/lib/library/NativeCallback.js +59 -0
  91. package/dist/esm/lib/library/NativeLibraryHandle.js +532 -0
  92. package/dist/esm/lib/library/Resolve.js +122 -0
  93. package/dist/esm/lib/thread/NativeThreads.js +377 -0
  94. package/dist/esm/lib/thread/NativeWorker.js +93 -0
  95. package/dist/esm/lib/thread/NativeWorkerCode.js +1 -0
  96. package/dist/esm/lib/thread/PackageRequire.js +2 -0
  97. package/dist/esm/lib/thread/ThreadProtocol.js +1 -0
  98. package/dist/types/components/NativeLibrary.d.ts +229 -0
  99. package/dist/types/decorators/Library.d.ts +61 -0
  100. package/dist/types/decorators/Native.d.ts +69 -0
  101. package/dist/types/exceptions/NativeDeclarationException.d.ts +12 -0
  102. package/dist/types/exceptions/NativeLibraryClosedException.d.ts +12 -0
  103. package/dist/types/exceptions/NativeLibraryNotFoundException.d.ts +11 -0
  104. package/dist/types/exceptions/NativeMemoryException.d.ts +11 -0
  105. package/dist/types/exports/FFI.d.ts +12 -0
  106. package/dist/types/exports/Generator.d.ts +2 -0
  107. package/dist/types/lib/Memory.d.ts +188 -0
  108. package/dist/types/lib/Runtime.d.ts +98 -0
  109. package/dist/types/lib/backend/Functions.d.ts +65 -0
  110. package/dist/types/lib/backend/KoffiTypes.d.ts +53 -0
  111. package/dist/types/lib/declarations/Builtins.d.ts +33 -0
  112. package/dist/types/lib/declarations/Layout.d.ts +41 -0
  113. package/dist/types/lib/declarations/Lexer.d.ts +40 -0
  114. package/dist/types/lib/declarations/Parser.d.ts +90 -0
  115. package/dist/types/lib/declarations/Platform.d.ts +50 -0
  116. package/dist/types/lib/declarations/Types.d.ts +173 -0
  117. package/dist/types/lib/generator/CText.d.ts +14 -0
  118. package/dist/types/lib/generator/Generator.d.ts +136 -0
  119. package/dist/types/lib/generator/Preprocessor.d.ts +60 -0
  120. package/dist/types/lib/generator/TypeScriptTypes.d.ts +35 -0
  121. package/dist/types/lib/library/NativeCallback.d.ts +44 -0
  122. package/dist/types/lib/library/NativeLibraryHandle.d.ts +268 -0
  123. package/dist/types/lib/library/Resolve.d.ts +49 -0
  124. package/dist/types/lib/thread/NativeThreads.d.ts +80 -0
  125. package/dist/types/lib/thread/NativeWorker.d.ts +6 -0
  126. package/dist/types/lib/thread/NativeWorkerCode.d.ts +5 -0
  127. package/dist/types/lib/thread/PackageRequire.d.ts +6 -0
  128. package/dist/types/lib/thread/ThreadProtocol.d.ts +77 -0
  129. package/package.json +85 -4
@@ -0,0 +1,35 @@
1
+ import { type CType, type FunctionType, type RecordType } from '../declarations/Types.js';
2
+ /**
3
+ * Where a value is: given to a native function (a parameter, the result of a JS callback), or given by it (a result, a
4
+ * member of a struct, an argument a JS callback receives)
5
+ */
6
+ export type Flow = 'given' | 'received';
7
+ /**
8
+ * The TypeScript types of C types, as the package converts their values
9
+ */
10
+ export declare class TypeScriptTypes {
11
+ #private;
12
+ /**
13
+ * Types for the declarations of a library.
14
+ * @param names The TypeScript names of its structs and unions.
15
+ */
16
+ constructor(names: ReadonlyMap<CType, string>);
17
+ /**
18
+ * The TypeScript type of a value of a C type.
19
+ * @param type The C type.
20
+ * @param flow Whether the value is given to the native code or received from it.
21
+ */
22
+ type(type: CType, flow: Flow): string;
23
+ /**
24
+ * The TypeScript type of a function: of a native function, or of a JS callback the native code calls.
25
+ * @param type The function type.
26
+ * @param callback Whether it is a JS callback (its arguments received, its result given).
27
+ */
28
+ functionType(type: FunctionType, callback?: boolean): string;
29
+ /**
30
+ * The members of a struct or a union, as the lines of an interface (or of an object type).
31
+ * @param record The struct or the union.
32
+ * @param indent The indentation of the lines.
33
+ */
34
+ members(record: RecordType, indent: string): string[];
35
+ }
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TypeScriptTypes = void 0;
4
+ const Types_js_1 = require("../declarations/Types.js");
5
+ /**
6
+ * The words TypeScript reserves: not names of parameters
7
+ */
8
+ const RESERVED = new Set([
9
+ 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'enum', 'export', 'extends', 'false',
10
+ 'finally', 'for', 'function', 'if', 'import', 'in', 'instanceof', 'new', 'null', 'return', 'super', 'switch', 'this', 'throw', 'true', 'try',
11
+ 'typeof', 'var', 'void', 'while', 'with', 'as', 'implements', 'interface', 'let', 'package', 'private', 'protected', 'public', 'static',
12
+ 'yield', 'await', 'arguments', 'eval'
13
+ ]);
14
+ /**
15
+ * The typed arrays of the arrays of numbers of the structs
16
+ */
17
+ const TYPED_ARRAYS = {
18
+ schar: 'Int8Array', int8: 'Int8Array', uchar: 'Uint8Array', uint8: 'Uint8Array', short: 'Int16Array', int16: 'Int16Array',
19
+ ushort: 'Uint16Array', uint16: 'Uint16Array', char16: 'Uint16Array', int: 'Int32Array', int32: 'Int32Array', uint: 'Uint32Array',
20
+ uint32: 'Uint32Array', char32: 'Uint32Array', float: 'Float32Array', double: 'Float64Array'
21
+ };
22
+ /**
23
+ * The name of a parameter in TypeScript: its C name, not a reserved word, not one of the others
24
+ * @param parameter
25
+ * @param index
26
+ * @param taken
27
+ */
28
+ function parameterName(parameter, index, taken) {
29
+ let name = parameter.name ?? `arg${index}`;
30
+ if (RESERVED.has(name))
31
+ name = `${name}_`;
32
+ while (taken.has(name))
33
+ name = `${name}_`;
34
+ taken.add(name);
35
+ return name;
36
+ }
37
+ /**
38
+ * The TypeScript types of C types, as the package converts their values
39
+ */
40
+ class TypeScriptTypes {
41
+ #names;
42
+ /**
43
+ * Types for the declarations of a library.
44
+ * @param names The TypeScript names of its structs and unions.
45
+ */
46
+ constructor(names) {
47
+ this.#names = names;
48
+ }
49
+ /**
50
+ * The TypeScript type of a value of a C type.
51
+ * @param type The C type.
52
+ * @param flow Whether the value is given to the native code or received from it.
53
+ */
54
+ type(type, flow) {
55
+ switch (type.kind) {
56
+ case 'primitive':
57
+ return this.#primitive(type.name, flow);
58
+ case 'enum':
59
+ return this.#primitive(type.base, flow);
60
+ case 'pointer':
61
+ return this.#pointer(type.to, type.constTarget, flow);
62
+ case 'array':
63
+ return this.#array(type.of);
64
+ case 'struct':
65
+ case 'union':
66
+ return this.#names.get(type) ?? this.#inline(type);
67
+ case 'function':
68
+ return this.#pointer(type, false, flow);
69
+ }
70
+ }
71
+ /**
72
+ * The TypeScript type of a function: of a native function, or of a JS callback the native code calls.
73
+ * @param type The function type.
74
+ * @param callback Whether it is a JS callback (its arguments received, its result given).
75
+ */
76
+ functionType(type, callback = false) {
77
+ const taken = new Set();
78
+ const parameters = type.parameters.map((parameter, index) => {
79
+ return `${parameterName(parameter, index, taken)}: ${callback ? this.type(parameter.type, 'received') : this.#parameter(parameter)}`;
80
+ });
81
+ if (type.variadic)
82
+ parameters.push('...args: unknown[]');
83
+ return `(${parameters.join(', ')}) => ${this.type(type.result, callback ? 'given' : 'received')}`;
84
+ }
85
+ /**
86
+ * The members of a struct or a union, as the lines of an interface (or of an object type).
87
+ * @param record The struct or the union.
88
+ * @param indent The indentation of the lines.
89
+ */
90
+ members(record, indent) {
91
+ return (record.members ?? []).map((member) => `${indent}${member.name}: ${this.type(member.type, 'received')}`);
92
+ }
93
+ /**
94
+ * A parameter of a native function: an output parameter as the array or the object filled
95
+ * @param parameter
96
+ */
97
+ #parameter(parameter) {
98
+ if (parameter.direction !== 'in' && parameter.type.kind === 'pointer') {
99
+ const to = parameter.type.to;
100
+ if ((to.kind === 'struct' || to.kind === 'union') && to.members)
101
+ return this.type(to, 'received');
102
+ return `Out<${this.type(to, 'received')}>`;
103
+ }
104
+ return this.type(parameter.type, 'given');
105
+ }
106
+ #primitive(name, flow) {
107
+ if (name === 'void')
108
+ return 'void';
109
+ if (name === 'bool')
110
+ return 'boolean';
111
+ if ((0, Types_js_1.primitiveBig)(name))
112
+ return flow === 'given' ? 'bigint | number' : 'bigint';
113
+ return 'number';
114
+ }
115
+ #pointer(to, constTarget, flow) {
116
+ //The strings: char, char16_t, wchar_t
117
+ if (to.kind === 'primitive' && (to.name === 'char' || to.name === 'char16' || to.name === 'wchar')) {
118
+ return flow === 'given' && !constTarget ? 'string | Buffer | null' : 'string | null';
119
+ }
120
+ if (to.kind === 'function' && flow === 'given')
121
+ return `(${this.functionType(to, true)}) | Pointer | null`;
122
+ if (flow !== 'given' || to.kind === 'function')
123
+ return 'Pointer | null';
124
+ //A struct or a union given to the function: its object too
125
+ if ((to.kind === 'struct' || to.kind === 'union') && to.members)
126
+ return `${this.type(to, 'received')} | Pointer | Buffer | ArrayBufferView | null`;
127
+ return 'Pointer | Buffer | ArrayBufferView | null';
128
+ }
129
+ #array(of) {
130
+ if (of.kind === 'primitive' || of.kind === 'enum') {
131
+ const name = of.kind === 'enum' ? of.base : of.name;
132
+ if (name === 'char' || name === 'wchar')
133
+ return 'string';
134
+ if ((0, Types_js_1.primitiveBig)(name))
135
+ return 'bigint[]';
136
+ if (name === 'bool')
137
+ return 'boolean[]';
138
+ return TYPED_ARRAYS[name] ?? 'number[]';
139
+ }
140
+ const element = this.type(of, 'received');
141
+ return /^[\w.]+$/.test(element) ? `${element}[]` : `Array<${element}>`;
142
+ }
143
+ /**
144
+ * A struct or a union without a name (an anonymous member): an object type
145
+ * @param record
146
+ */
147
+ #inline(record) {
148
+ if (!record.members)
149
+ return 'Pointer';
150
+ return `{${record.members.map((member) => `${member.name}: ${this.type(member.type, 'received')}`).join(', ')}}`;
151
+ }
152
+ }
153
+ exports.TypeScriptTypes = TypeScriptTypes;
@@ -0,0 +1,44 @@
1
+ import type { Pointer } from '../Runtime.js';
2
+ /**
3
+ * A JS function a library can call at any time (a persistent callback), made by `callback()` of a library: give its
4
+ * `pointer` to the library, and release it when the library no longer calls it. The callbacks of a library are released
5
+ * when it is closed; a process has at most 8192 of them at a time.
6
+ *
7
+ * When it is called from another thread of the library, it runs in the JS thread once the event loop gets to it. An
8
+ * exception it throws goes to the error handler of its library (the `error` event of a component), and the library gets
9
+ * zero (or a null pointer) as its result.
10
+ * @example
11
+ * ```typescript
12
+ * import {loadNativeLibrary, type NativeCallback} from '@lakutata/ffi'
13
+ *
14
+ * const vendor = loadNativeLibrary('vendor', 'typedef void (*vendor_log)(int level, const char *message);')
15
+ * const setLogger = vendor.func<(logger: bigint | null) => void>('void vendor_set_logger(vendor_log logger)')
16
+ * const logger: NativeCallback = vendor.callback('vendor_log', (level: number, message: string): void => console.log(level, message))
17
+ * setLogger(logger.pointer)
18
+ * //Once the library no longer calls it
19
+ * setLogger(null)
20
+ * logger.release()
21
+ * ```
22
+ */
23
+ export declare class NativeCallback {
24
+ #private;
25
+ /**
26
+ * A registered callback (made by `callback()` of a library, not by this constructor).
27
+ * @param pointer Its pointer.
28
+ * @param onRelease Called once it is released.
29
+ */
30
+ constructor(pointer: Pointer, onRelease: (callback: NativeCallback) => void);
31
+ /**
32
+ * The pointer to give to the library: the address of a C function calling the JS function.
33
+ */
34
+ get pointer(): Pointer;
35
+ /**
36
+ * Whether it is released: the library must not call it any more.
37
+ */
38
+ get released(): boolean;
39
+ /**
40
+ * Release it: its pointer is no longer valid, its slot is free for another callback. Releasing it again does
41
+ * nothing.
42
+ */
43
+ release(): void;
44
+ }
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.NativeCallback = void 0;
7
+ const koffi_1 = __importDefault(require("koffi"));
8
+ /**
9
+ * A JS function a library can call at any time (a persistent callback), made by `callback()` of a library: give its
10
+ * `pointer` to the library, and release it when the library no longer calls it. The callbacks of a library are released
11
+ * when it is closed; a process has at most 8192 of them at a time.
12
+ *
13
+ * When it is called from another thread of the library, it runs in the JS thread once the event loop gets to it. An
14
+ * exception it throws goes to the error handler of its library (the `error` event of a component), and the library gets
15
+ * zero (or a null pointer) as its result.
16
+ * @example
17
+ * ```typescript
18
+ * import {loadNativeLibrary, type NativeCallback} from '@lakutata/ffi'
19
+ *
20
+ * const vendor = loadNativeLibrary('vendor', 'typedef void (*vendor_log)(int level, const char *message);')
21
+ * const setLogger = vendor.func<(logger: bigint | null) => void>('void vendor_set_logger(vendor_log logger)')
22
+ * const logger: NativeCallback = vendor.callback('vendor_log', (level: number, message: string): void => console.log(level, message))
23
+ * setLogger(logger.pointer)
24
+ * //Once the library no longer calls it
25
+ * setLogger(null)
26
+ * logger.release()
27
+ * ```
28
+ */
29
+ class NativeCallback {
30
+ #pointer;
31
+ #onRelease;
32
+ #released = false;
33
+ /**
34
+ * A registered callback (made by `callback()` of a library, not by this constructor).
35
+ * @param pointer Its pointer.
36
+ * @param onRelease Called once it is released.
37
+ */
38
+ constructor(pointer, onRelease) {
39
+ this.#pointer = pointer;
40
+ this.#onRelease = onRelease;
41
+ }
42
+ /**
43
+ * The pointer to give to the library: the address of a C function calling the JS function.
44
+ */
45
+ get pointer() {
46
+ return this.#pointer;
47
+ }
48
+ /**
49
+ * Whether it is released: the library must not call it any more.
50
+ */
51
+ get released() {
52
+ return this.#released;
53
+ }
54
+ /**
55
+ * Release it: its pointer is no longer valid, its slot is free for another callback. Releasing it again does
56
+ * nothing.
57
+ */
58
+ release() {
59
+ if (this.#released)
60
+ return;
61
+ this.#released = true;
62
+ koffi_1.default.unregister(this.#pointer);
63
+ this.#onRelease(this);
64
+ }
65
+ }
66
+ exports.NativeCallback = NativeCallback;
@@ -0,0 +1,268 @@
1
+ import { type Pointer } from '../Runtime.js';
2
+ import { NativeCallback } from './NativeCallback.js';
3
+ import { type LibraryNames } from './Resolve.js';
4
+ /**
5
+ * Where a library is found, and how it is closed
6
+ */
7
+ export interface NativeLibraryOptions {
8
+ /**
9
+ * The file of the library: the only one tried when given.
10
+ */
11
+ path?: string;
12
+ /**
13
+ * The directories tried before the ones of the system, in their order (aliases of the application allowed).
14
+ */
15
+ search?: string[];
16
+ /**
17
+ * The directory of the libraries of a packaged application, tried after the search directories.
18
+ */
19
+ packaged?: string;
20
+ /**
21
+ * Whether the library stays loaded once closed (its callbacks are released all the same).
22
+ * @default false
23
+ */
24
+ keepLoaded?: boolean;
25
+ /**
26
+ * On Windows, the C library the functions of the library use, whose errno `errno()` reads.
27
+ * @default 'ucrtbase.dll'
28
+ */
29
+ crt?: string;
30
+ /**
31
+ * Handles the exceptions thrown by the persistent callbacks (the library gets zero as their result).
32
+ * @default writes them to the console
33
+ */
34
+ onCallbackError?: (error: unknown) => void;
35
+ /**
36
+ * The worker threads of the library, which run its asynchronous functions: 0 for the thread pool of the runtime
37
+ * (the one of libuv in Node.js, shared with the file system); with one thread, the asynchronous calls run one after
38
+ * the other, in their order (a library that is not thread-safe). The synchronous functions run in the thread
39
+ * calling them.
40
+ * @default 0
41
+ */
42
+ threads?: number;
43
+ }
44
+ /**
45
+ * How a function is bound
46
+ */
47
+ export interface NativeFunctionOptions {
48
+ /**
49
+ * Whether it runs in another thread, returning a promise: for the functions that block. It runs in the threads of
50
+ * the library when it has some (`threads`), else in the thread pool of the runtime (Node.js runs them in the pool
51
+ * of libuv, 4 threads by default, shared with the file system: raise UV_THREADPOOL_SIZE for many of them), where a
52
+ * variadic function cannot be asynchronous.
53
+ * @default false
54
+ */
55
+ async?: boolean;
56
+ /**
57
+ * Frees the strings the function gives (its result, its output strings) once read: the name of the function of the
58
+ * library that frees them (`sqlite3_free`), or true for free() of the C library. On Windows, a library built with
59
+ * another C library must be given its own function.
60
+ */
61
+ free?: string | boolean;
62
+ /**
63
+ * Its 64-bit integers (its result, its output integers) as numbers rather than bigints: a RangeError when one is not
64
+ * a safe integer.
65
+ * @default 'bigint'
66
+ */
67
+ int64?: 'bigint' | 'number';
68
+ }
69
+ /**
70
+ * A variable a library exports
71
+ */
72
+ export interface NativeVariableAccessor<T = unknown> {
73
+ /**
74
+ * Its address.
75
+ */
76
+ readonly address: Pointer;
77
+ /**
78
+ * Its value (an array of char of unknown length is read as a string).
79
+ */
80
+ get(): T;
81
+ /**
82
+ * Change its value.
83
+ * @param value The value.
84
+ * @throws {NativeDeclarationException} When it is const.
85
+ */
86
+ set(value: T): void;
87
+ }
88
+ /**
89
+ * A native library loaded with its declarations, without the container (scripts, tests): its functions, variables and
90
+ * callbacks, and the native memory read and written with its types. Made by {@link loadNativeLibrary}; a
91
+ * `NativeLibrary` component holds one.
92
+ * @example
93
+ * ```typescript
94
+ * import {loadNativeLibrary, type NativeLibraryHandle} from '@lakutata/ffi'
95
+ *
96
+ * const libc: NativeLibraryHandle = loadNativeLibrary('c', 'typedef struct { int quot; int rem; } div_t;')
97
+ * const div = libc.func<(numerator: number, denominator: number) => {quot: number, rem: number}>('div_t div(int numerator, int denominator)')
98
+ * console.log(div(17, 5))
99
+ * await libc.close()
100
+ * ```
101
+ */
102
+ export declare class NativeLibraryHandle {
103
+ #private;
104
+ /**
105
+ * Load a library (see {@link loadNativeLibrary}).
106
+ * @param names Its file names: one, or one by platform; `c` for the C library.
107
+ * @param declarations Its C declarations: the types, functions and variables its functions use.
108
+ * @param options Where it is found, how it is closed.
109
+ */
110
+ constructor(names: LibraryNames, declarations?: string, options?: NativeLibraryOptions);
111
+ /**
112
+ * The file the library was loaded from.
113
+ */
114
+ get file(): string;
115
+ /**
116
+ * Whether it is closed.
117
+ */
118
+ get closed(): boolean;
119
+ /**
120
+ * The asynchronous calls running.
121
+ */
122
+ get pending(): number;
123
+ /**
124
+ * The worker threads of the library (0: the asynchronous calls run in the thread pool of the runtime).
125
+ */
126
+ get threads(): number;
127
+ /**
128
+ * Settled once the threads of the library have loaded it (at once without threads): rejected with the error of a
129
+ * thread that could not. The asynchronous calls wait for them anyway.
130
+ */
131
+ get ready(): Promise<void>;
132
+ /**
133
+ * The constants of its declarations: the values of the enumerations, of the static constants and of the macros whose
134
+ * value is an integer.
135
+ */
136
+ get constants(): Readonly<Record<string, bigint>>;
137
+ /**
138
+ * Add C declarations to the ones of the library (and of the libraries loaded with the same declarations, which share
139
+ * them).
140
+ * @param text The declarations.
141
+ */
142
+ declare(text: string): void;
143
+ /**
144
+ * A function of the library, from its prototype: the function of koffi itself when nothing has to be converted.
145
+ * @param prototype Its C prototype, with the types of the declarations: `int sqlite3_open(const char *filename,
146
+ * _Out_ sqlite3 **db)`.
147
+ * @param options Whether it is asynchronous, how its strings are freed, how its 64-bit integers are given.
148
+ * @returns The function.
149
+ */
150
+ func<T extends (...args: any[]) => any = (...args: any[]) => any>(prototype: string, options?: NativeFunctionOptions): T;
151
+ /**
152
+ * A function of the declarations, by its name.
153
+ * @param name Its name.
154
+ * @param options Whether it is asynchronous, how its strings are freed, how its 64-bit integers are given.
155
+ * @returns The function.
156
+ */
157
+ function<T extends (...args: any[]) => any = (...args: any[]) => any>(name: string, options?: NativeFunctionOptions): T;
158
+ /**
159
+ * A variable the library exports: declared in the declarations (`extern const char sqlite3_version[];`), or by the
160
+ * declaration given.
161
+ * @param declaration Its name, or its declaration.
162
+ * @returns Its address, and the functions reading and writing its value.
163
+ */
164
+ variable<T = unknown>(declaration: string): NativeVariableAccessor<T>;
165
+ /**
166
+ * A persistent callback: a JS function the library can call at any time, released by `release()` or when the
167
+ * library is closed.
168
+ * @param type Its type: the name of a pointer-to-function type of the declarations (`vendor_log`), or its prototype
169
+ * (`void vendor_log(int level, const char *message)`).
170
+ * @param callback The JS function.
171
+ * @returns The callback, whose `pointer` is given to the library.
172
+ */
173
+ callback(type: string, callback: (...args: any[]) => any): NativeCallback;
174
+ /**
175
+ * Read native memory, as a type of the declarations: a value, or an array of values.
176
+ * @param pointer The address.
177
+ * @param type The type: `int`, `struct timeval`, `char *` (a string).
178
+ * @param count The number of values, for an array.
179
+ * @returns The value, or the array.
180
+ */
181
+ read<T = unknown>(pointer: Pointer, type: string, count?: number): T;
182
+ /**
183
+ * Write a value to native memory, as a type of the declarations.
184
+ * @param pointer The address.
185
+ * @param type The type.
186
+ * @param value The value.
187
+ */
188
+ write(pointer: Pointer, type: string, value: unknown): void;
189
+ /**
190
+ * The size of a type of the declarations, in bytes.
191
+ * @param type The type.
192
+ */
193
+ sizeOf(type: string): number;
194
+ /**
195
+ * The offset of a member of a struct of the declarations, in bytes.
196
+ * @param type The struct.
197
+ * @param member The member.
198
+ */
199
+ offsetOf(type: string, member: string): number;
200
+ /**
201
+ * Allocate native memory for values of a type of the declarations: memory that does not move, which the library can
202
+ * keep; freed by `free()`, or when the library is closed.
203
+ * @param type The type.
204
+ * @param count The number of values.
205
+ * @returns Its address.
206
+ */
207
+ alloc(type: string, count?: number): Pointer;
208
+ /**
209
+ * Free memory allocated by `alloc()`.
210
+ * @param pointer Its address.
211
+ */
212
+ free(pointer: Pointer): void;
213
+ /**
214
+ * The errno of the last call of this thread (on Windows, the one of the C library given by the `crt` option); with
215
+ * threads, the one of the thread of the last asynchronous call completed (reliable with one thread, or when the
216
+ * asynchronous calls are awaited one at a time).
217
+ */
218
+ errno(): number;
219
+ /**
220
+ * The last error of the Windows API (GetLastError) after the last call of this thread; with threads, the one of the
221
+ * thread of the last asynchronous call completed; undefined on the other systems.
222
+ */
223
+ windowsError(): number | undefined;
224
+ /**
225
+ * The asynchronous calls running, once they have all returned.
226
+ * @param timeout How long to wait at most, in milliseconds.
227
+ * @returns Whether they have all returned.
228
+ */
229
+ drain(timeout?: number): Promise<boolean>;
230
+ /**
231
+ * Close the library: new asynchronous calls are refused, the running ones awaited (a worker thread stopped during
232
+ * one crashes Bun), the callbacks released, the memory of `alloc()` freed, the library unloaded (unless kept
233
+ * loaded; musl never unloads). Its functions must not be called any more: a function of an unloaded library ends
234
+ * the process. When calls still run after the timeout, the ones in the thread pool go on, the ones in the threads
235
+ * of the library are rejected (their threads end once they return), and the library, its callbacks and its memory
236
+ * are left as they are: a call returning into an unloaded library, or calling a released callback, would end the
237
+ * process.
238
+ * @param timeout How long to wait for the asynchronous calls, in milliseconds.
239
+ */
240
+ close(timeout?: number): Promise<void>;
241
+ }
242
+ /**
243
+ * Load a native library with its C declarations, without the container (scripts, tests); in an application, declare a
244
+ * `NativeLibrary` component instead. The library is looked for in the directories of `search`, then where the system
245
+ * looks for libraries.
246
+ * @param names Its file names: one (`sqlite3`, completed as the platform names libraries), one by platform
247
+ * (`{darwin: 'libsqlite3.dylib', linux: 'libsqlite3.so.0', win32: 'winsqlite3.dll'}`), or `c` for the C library.
248
+ * @param declarations Its C declarations: the types its functions use, its functions, its variables, its constants.
249
+ * @param options Where it is found, how it is closed.
250
+ * @returns The library.
251
+ * @throws {NativeLibraryNotFoundException} When it cannot be loaded (the message lists what was tried).
252
+ * @throws {NativeDeclarationException} When the declarations cannot be read.
253
+ * @example
254
+ * ```typescript
255
+ * import {loadNativeLibrary, type Out, type Pointer} from '@lakutata/ffi'
256
+ *
257
+ * const sqlite = loadNativeLibrary({darwin: 'libsqlite3.dylib', linux: 'libsqlite3.so.0', win32: 'winsqlite3.dll'}, `
258
+ * typedef struct sqlite3 sqlite3;
259
+ * #define SQLITE_OK 0
260
+ * `)
261
+ * const open = sqlite.func<(filename: string, db: Out<Pointer>) => number>('int sqlite3_open(const char *filename, _Out_ sqlite3 **db)')
262
+ * const close = sqlite.func<(db: Pointer) => number>('int sqlite3_close(sqlite3 *db)')
263
+ * const db: Out<Pointer> = [null]
264
+ * if (open(':memory:', db) === Number(sqlite.constants.SQLITE_OK)) close(db[0]!)
265
+ * await sqlite.close()
266
+ * ```
267
+ */
268
+ export declare function loadNativeLibrary(names: LibraryNames, declarations?: string, options?: NativeLibraryOptions): NativeLibraryHandle;