11About
22=====
33
4- Foreign Function Interface helper. Provides a friendly abstraction/API for:
4+ Foreign Function Interface (FFI) helper. Provides a friendly abstraction/API for:
55
66- [ ffi-napi] ( https://www.npmjs.com/package/ffi-napi ) (MIT)
77- [ koffi] ( https://www.npmjs.com/package/koffi ) (MIT)
@@ -101,6 +101,11 @@ npm install @xan105/ffi
101101Please note that ` ffi-napi ` and ` koffi ` are optional peer dependencies.<br />
102102Install the one you wish to use yourself (or both 🙃).
103103
104+ ### ⚛️ Electron
105+
106+ ⚠️ NB: As of this writing ` ffi-napi ` does not work with Electron >= 21.x.<br />
107+ Due to [ Electron and the V8 Memory Cage] ( https://www.electronjs.org/blog/v8-memory-cage ) .
108+
104109API
105110===
106111
@@ -120,24 +125,29 @@ import ... from "@xan105/ffi/koffi";
120125
121126Load the given library path and return an handle function to call library's symbol(s).
122127
123- ** Option**
128+ ⚙️ ** Option**
124129
125130- ` ignoreLoadingFail?: boolean ` (false)
126131
127- Silent fail if the given library couldn't be loaded.<br />
128- 💡 Handle will return ` undefined ` in that case.
132+ When set to ` true ` the handle function will silently fail if the given library couldn't be loaded and return ` undefined ` in such case.
129133
130134- ` ignoreMissingSymbol?: boolean ` (false)
131135
132- Silent fail if the given library doesn't have the called symbol.<br />
133- 💡 Handle will return ` undefined ` in that case.
136+ When set to ` true ` the handle function will silently fail if the given library doesn't have the called symbol and return ` undefined ` in such case.
137+
138+ - ` lazy ` (false)
134139
135- - ` abi?: string ` ("func" for koffi and "default_abi" for ffi-napi)
140+ When set to ` true ` use ` RTLD_LAZY ` (lazy-binding) on POSIX platforms otherwise use ` RTLD_NOW ` .
136141
137- ABI convention to use. Use this when you need to ex: winapi x86 requires "stdcall".
142+ - ` abi?: string ` (koffi: "func" | ffi-napi: "default_abi")
143+
144+ ABI convention to use. Use this when you need to.<br />
145+ _ ex: winapi x86 requires "stdcall"._
138146
139147** Return**
140148
149+ An handle function to call library's symbol(s).
150+
141151``` ts
142152function (symbol : string | number , result : unknown , parameters : unknown []): unknown
143153```
@@ -153,21 +163,20 @@ See the corresponding FFI library for more information on what to pass for `resu
153163` ` ` js
154164import { load } from "@xan105/ffi/[ napi | koffi ]";
155165const lib = load("libm");
156- const ceil = lib("ceil", "double", ["double"])
166+ const ceil = lib("ceil", "double", ["double"]);
157167ceil(1.5); //2
158168` ` `
159169
160170#### ` dlopen(path: string, symbols: object, option?: object): object `
161171
162- Open library and define exported symbols . This is a friendly wrapper to ` load() ` inspired by Deno FFI ` dlopen ` syntax .
163-
172+ Open library and define exported symbols . This is a friendly wrapper to ` load() ` inspired by Deno FFI ` dlopen ` syntax .< br / >
164173If you ever use ffi - napi ` ffi.Library() ` this will be familiar .
165174
166175** Param **
167176
168177- ` path: string `
169178
170- Library path to load
179+ Library path to load .
171180
172181- ` symbols: object `
173182
@@ -176,28 +185,50 @@ If you ever use ffi-napi `ffi.Library()` this will be familiar.
176185` ` ` ts
177186 {
178187 name: {
188+ symbol?: string | number,
179189 result?: unknown,
180190 parameters?: unknown[],
181191 nonblocking?: boolean,
182- symbol ?: string | number
192+ stub ?: boolean
183193 },
184194 ...
185195 }
186196` ` `
197+
198+ By default the property ` name ` is used for ` symbol ` . Use ` symbol ` if you are using a symbol name different than the given property name or if you want to call by ordinal (Koffi ).
187199
188- By default the property name is used for ` symbol ` when omitted . Use ` symbol ` if you are using a different name than the symbol name or if you want to call by ordinal (Koffi ).
200+ ` result ` and ` parameters ` are the same as for the returned handle from ` load() ` .<br />
201+ If omitted , ` result ` is set to " void" and ` parameters ` to an empty array .< br / >
202+ See the corresponding FFI library for more information on what to pass for ` result ` and ` parameters ` as they have string type parser , structure / array / pointer interface , ... and other features .
189203
190- When ` nonblocking ` is ` true ` ( default false ) this will return the promisified ` async() ` method of the corresponding symbol ( see corresponding ffi library asynchronous calling ). The rest is the same as for ` load() ` .
204+ When ` nonblocking ` is ` true ` the corresponding symbol will return the promisified ` async() ` method ( asynchronous calling ). 💡 If set , this superseed the _ " global " _ ` nonblocking ` option ( see below ) .
191205
192- - option ?: object
206+ When ` stub ` is ` true ` the corresponding symbol will return a no - op if its missing .< br / >
207+ 💡 If set , this superseed the _ " global" _ ` stub ` option (see below ).
208+
209+ - ⚙️ ` option?: object `
193210
194- Pass option (s ) to ` load() ` . See above .
211+ Same as ` load() ` (see above ) in addition to the following :
212+
213+ + ` errorAtRuntime?: boolean ` (false )
214+
215+ When set to ` true ` , initialisation error will be thrown on symbol invocation .
216+
217+ + ` nonblocking?: boolean ` (false )
218+
219+ When set to ` true ` , every symbols will return the corresponding promisified ` async() ` method (asynchronous calling ).< br / >
220+ 💡 This can be overriden per symbol (see symbol definition above ).
221+
222+ + ` stub?: boolean ` (false )
223+
224+ When set to ` true ` , every missing symbols will return a no - op .< br / >
225+ 💡 This can be overriden per symbol (see symbol definition above ).
195226
196227** Return **
197228
198229 An object with the given symbol (s ) as properties .
199230
200- ❌ Throws on error
231+ ❌ Throws on error .
201232
202233** Example **
203234
@@ -348,9 +379,54 @@ library.doSomething();
348379callback .close ();
349380```
350381
351- #### ` pointer(value: unknown, direction?: string): any `
382+ #### ` pointer(value: unknown, direction?: string): unknown `
352383
353- Just a shorthand to ` ref.refType(x) ` (ffi-napi) and ` koffi.out/inout(koffi.pointer(x)) ` (koffi) to define a pointer.
384+ Just a shorthand to define a pointer.
385+
386+ ``` js
387+ import { dlopen , types , pointer } from " @xan105/ffi/[ napi | koffi ]" ;
388+
389+ const dylib = dlopen (" shell32.dll" , {
390+ SHQueryUserNotificationState: {
391+ result: types .win32 .HRESULT ,
392+ parameters: [
393+ pointer (types .win32 .ENUM , " out" )
394+ ]
395+ }
396+ }, { abi: " stdcall" });
397+ ```
398+
399+ #### ` struct(schema: unknown): unknown `
400+
401+ Just a shorthand to define a structure.
402+
403+ ``` js
404+ import { dlopen , types , struct , pointer } from " @xan105/ffi/[ napi | koffi ]" ;
405+
406+ const POINT = struct ({ // define struct
407+ x: types .win32 .LONG ,
408+ y: types .win32 .LONG
409+ });
410+
411+ const dylib = dlopen (" user32.dll" , { // lib loading
412+ GetCursorPos: {
413+ result: types .win32 .BOOL ,
414+ parameters: [ pointer (POINT , " out" ) ] // struct pointer
415+ }
416+ }, { abi: " stdcall" });
417+
418+ // ⚠️ NB: Struct are use differently afterwards:
419+
420+ // Koffi
421+ const cursorPos = {};
422+ GetCursorPos (cursorPos);
423+ console .log (cursorPos) // { x: 0, y: 0 }
424+
425+ // ffi-napi
426+ const cursorPos = new POINT ();
427+ getCursorPos (cursorPos .ref ());
428+ console .log ({ x: cursorPos .x , y: cursorPos .y });
429+ ```
354430
355431#### ` alloc(type: unknown): { pointer: Buffer, get: ()=> unknown } `
356432
@@ -363,4 +439,26 @@ const dylib = dlopen(...); //lib loading
363439const number = alloc (" int" ); // allocate Buffer for the output data
364440dylib .manipulate_number (number .pointer );
365441const result = number .get ();
442+ ```
443+
444+ #### ` lastError(option?: object): string[] | number `
445+
446+ Shorthand to errno (POSIX) and GetLastError (win32).
447+
448+ ⚙️ ** Option**
449+
450+ - ` translate?: boolean ` (true)
451+
452+ When an error code is known it will be 'translated' to its corresponding message and code values as<br /> ` [message: string, code?: string] ` . If you only want the raw numerical code set it to ` false ` .
453+
454+ eg:
455+ ``` js
456+ if (result !== 0 ){ // something went wrong
457+
458+ console .log (lastError ())
459+ // ['No such file or directory', 'ENOENT']
460+
461+ console .log (lastError ({ translate: false }));
462+ // 2
463+ }
366464```
0 commit comments