Gathering detailed insights and metrics for @jellybrick/ffi-cjs
Gathering detailed insights and metrics for @jellybrick/ffi-cjs
Friendly abstraction/API for FFI with a Deno like syntax
npm install @jellybrick/ffi-cjs
Typescript
Module System
Min. Node Version
Node Version
NPM Version
JavaScript (100%)
Total Downloads
302
Last Day
2
Last Week
4
Last Month
20
Last Year
141
5 Stars
70 Commits
2 Forks
1 Watching
1 Branches
1 Contributors
Latest Version
0.7.0
Package Id
@jellybrick/ffi-cjs@0.7.0
Unpacked Size
32.25 kB
Size
9.35 kB
File Count
19
NPM Version
9.7.2
Node Version
18.13.0
Publised On
08 Jul 2023
Cumulative downloads
Total Downloads
Last day
0%
2
Compared to previous day
Last week
33.3%
4
Compared to previous week
Last month
400%
20
Compared to previous month
Last year
-12.4%
141
Compared to previous year
1
Foreign Function Interface helper. Provides a friendly abstraction/API for:
Syntax is inspired by Deno FFI. The goal was to be able to easily switch from ffi-napi
to koffi
or vice versa.
📦 Scoped @xan105
packages are for my own personal use but feel free to use them.
@xan105/ffi
(MIT)Loading a library with Deno like syntax
1import { dlopen } from "@jellybrick/ffi-cjs/[ napi | koffi ]"; 2 3const lib = dlopen("libm", { 4 ceil: { 5 result: "double", 6 parameters: [ "double" ] 7 } 8}); 9lib.ceil(1.5); // 2
Async
1import { dlopen } from "@jellybrick/ffi-cjs/[ napi | koffi ]"; 2 3const lib = dlopen("libm", { 4 ceil: { 5 result: "double", 6 parameters: [ "double" ], 7 nonblocking: true 8 } 9}); 10await lib.ceil(1.5); // 2
Calling directly from a library
1import { load, types } from "@jellybrick/ffi-cjs/[ napi | koffi ]"; 2 3const call = load("user32.dll", { abi: "stdcall" }); 4const MessageBoxA = call("MessageBoxA", "int", [ 5 "void *", 6 types.win32.LPCSTR, 7 types.win32.LPCSTR, 8 "uint" 9]); 10 11const MB_ICONINFORMATION = 0x40; 12MessageBoxA(null, "Hello World!", "Message", MB_ICONINFORMATION);
Callback with Deno like syntax
1import { dlopen, Callback} from "@jellybrick/ffi-cjs/koffi"; 2 3const library = dlopen( 4 "./callback.so", 5 { 6 set_status_callback: { 7 parameters: ["function"], 8 result: "void" 9 }, 10 start_long_operation: { 11 parameters: [], 12 result: "void" 13 } 14 } 15); 16 17const callback = new Callback( 18 { 19 parameters: ["u8"], 20 result: "void", 21 }, 22 (success) => {} 23); 24 25library.set_status_callback(callback.pointer); 26library.start_long_operation();
npm install @jellybrick/ffi-cjs
Please note that ffi-napi
and koffi
are optional peer dependencies.
Install the one you wish to use yourself (or both 🙃).
⚠️ This module is only available as an CommonJS module (CJS).
💡 This lib doesn't have a default entry point. Choose the export corresponding to your liking.
1import ... from "@jellybrick/ffi-cjs/napi"; 2//OR 3import ... from "@jellybrick/ffi-cjs/koffi";
1const ... = require("@jellybrick/ffi-cjs/napi"); 2//OR 3const ... = require("@jellybrick/ffi-cjs/koffi");
load(path: string, option?: object): function
Load the given library path and return an handle function to call library's symbol(s).
Option
ignoreLoadingFail?: boolean
(false)Silent fail if the given library couldn't be loaded.
💡 Called symbol will be undefined
in that case.
ignoreMissingSymbol?: boolean
(false)Silent fail if the given library doesn't have the called symbol.
💡 Called symbol will be undefined
in that case.
abi?: string
("func" for koffi and "default_abi" for ffi-napi)ABI convention to use. Use this when you need to ex: winapi x86 requires "stdcall".
Return
1function(symbol: string | number, result: unknown, parameters: unknown[]): any;
💡 Koffi
can call by ordinal (symbol:number)
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.
❌ Throws on error
Example:
1import { load } from "@jellybrick/ffi-cjs/[ napi | koffi ]"; 2const call = load("libm"); 3 4const ceil = call("ceil", "double", ["double"]) 5ceil(1.5); //2
dlopen(path: string, symbols: object, option?: object): object
Open library and define exported symbols. This is a friendly wrapper to load()
inspired by Deno FFI dlopen
syntax.
If you ever use ffi-napi ffi.Library()
this will be familiar.
Param
path: string
Library path to load
symbols: object
Symbol(s) definition:
1 { 2 name: { 3 result?: unknown, 4 parameters?: unknown[], 5 nonblocking?: boolean, 6 symbol?: string | number 7 }, 8 ... 9 }
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).
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()
.
option?: object
Pass option(s) to load()
. See above.
Return
An object with the given symbol(s) as properties.
❌ Throws on error
Example
1import { dlopen, types } from "@jellybrick/ffi-cjs/[ napi | koffi ]"; 2const { BOOL } = types.win32; 3 4const lib = dlopen("xinput1_4", { 5 "XInputEnable": { 6 parameters: [BOOL], 7 nonblocking: true 8 } 9}, { abi: "stdcall" }); 10 11await lib.XInputEnable(1);
const types: object
The FFI Library's primitive types as well as corresponding alias are exposed for convenience. Such as Deno types (rust) and Windows specific types (DWORD,...).
💡 Windows specific types are grouped together under win32
.
1import { types } from "@jellybrick/ffi-cjs/[ napi | koffi ]"; 2const { DWORD, LPCSTR } = types.win32;
💡 When using koffi
alias are also set with koffi.alias()
so you can use them as string.
1import { load } from "@jellybrick/ffi-cjs/koffi"; 2const call = load("user32.dll", { abi: "stdcall" }); 3const MessageBoxA = call("MessageBoxA", "int", ["void *", "LPCSTR", "LPCSTR", "uint"]);
⚠️ Types are not exposed under their own namespace because some words are illegal or already in use in JavaScript. You can still use destructuring if needed as long as the name is "allowed".
❌ No
import { i32 } from "@jellybrick/ffi-cjs/koffi/types"
✔️ Yes
import { types } from "@jellybrick/ffi-cjs/koffi"
const { i32 } = types;
🚫 Forbidden
import { types } from "@jellybrick/ffi-cjs/napi"
const { function } = types;
class Callback
Create a callback to be called at a later time (registered callback).
This is a class wrapper to the FFI library's callback function(s) inspired by Deno FFI UnsafeCallback class
syntax.
(definition: { result: unknown, parameters: unknown[] }, callback?: Function | null)
pointer: unknown
The pointer to the callback.
address: number | BigInt | null
The memory address of the pointer.
type: unknown
The type of the callback.
close(): void
Dispose of the callback. Remove function pointer associated with this instance.
register(callback?: Function): void
Register the callback. If a callback was already registered with this instance it will be disposed of.
1import { dlopen, types, Callback } from "@jellybrick/ffi-cjs/[ napi | koffi ]"; 2 3const library = dlopen("./callback.so", { 4 setCallback: { 5 parameters: [types.function], 6 result: "void", 7 }, 8 doSomething(): { 9 parameters: [], 10 result: "void", 11 }, 12}); 13 14const callback = new Callback( 15 { parameters: [], result: "void" }, 16 () => {}, 17); 18 19library.setCallback(callback.pointer); 20library.doSomething(); 21 22// After callback is no longer needed 23callback.close();
You can also register the callback at a later time:
1import { dlopen, Callback } from "@jellybrick/ffi-cjs/[ napi | koffi ]"; 2 3const callback = new Callback( 4 { parameters: [], result: "void" } 5); 6 7const library = dlopen("./callback.so", { 8 setCallback: { 9 parameters: [callback.type], 10 result: "void", 11 }, 12 doSomething(): { 13 parameters: [], 14 result: "void", 15 }, 16}); 17 18callback.register(()=>{}); 19 20library.setCallback(callback.pointer); 21library.doSomething(); 22 23// After callback is no longer needed 24callback.close();
pointer(value: unknown, direction?: string): any
Just a shorthand to ref.refType(x)
(ffi-napi) and koffi.out/inout(koffi.pointer(x))
(koffi) to define a pointer.
alloc(type: unknown): { pointer: Buffer, get: ()=> unknown }
Allocate a buffer and get the corresponding data when passing a pointer to allow the called function to manipulate memory.
1import { dlopen, alloc } from "@jellybrick/ffi-cjs/[ napi | koffi ]"; 2const dylib = dlopen(...); //lib loading 3 4const number = alloc("int"); //allocate Buffer for the output data 5dylib.manipulate_number(number.pointer); 6const result = number.get();
No vulnerabilities found.
No security vulnerabilities found.