1.2.0 • Published 5 years ago

@glencfl/ffi-napi-di v1.2.0

Weekly downloads
4
License
MIT
Repository
github
Last release
5 years ago

@glencfl/ffi-napi-di

Node.js Foreign Function Interface for N-API

node-ffi-napi is a Node.js addon for loading and calling dynamic libraries using pure JavaScript. It can be used to create bindings to native libraries without writing any C++ code.

It also simplifies the augmentation of node.js with C code as it takes care of handling the translation of types across JavaScript and C, which can add reams of boilerplate code to your otherwise simple C. See the example/factorial for an example of this use case.

WARNING: node-ffi-napi assumes you know what you're doing. You can pretty easily create situations where you will segfault the interpreter and unless you've got C debugger skills, you probably won't know what's going on.

WARNING: The original API of node-ffi is left mostly untouched in the N-API wrapper. However, the API did not have very well-defined properties in the context of garbage collection and multi-threaded execution. It is recommended to avoid any multi-threading usage of this library if possible.

Differences to ffi-napi

  • This module utilizes @glencfl/ref-napi-di instead of ref-napi.
  • This module takes its native .node dependency via dependency injection, allowing it to be used in more restricted environments.
  • The native code has been moved out into the @glencfl/ffi-napi-binding package.
  • A TypeScript definition file has been bundled, with types being available through the global FFI namespace.

Installation

This package is available through NPM as @glencfl/ffi-napi-di. This package is primarily intended to be used alongside the following packages:

Installation of all using yarn:

yarn add @glencfl/ref-napi-binding @glencfl/ref-napi-di @glencfl/ffi-napi-binding @glencfl/ffi-napi-di

Example

var refBinding = require('@glencfl/ref-napi-binding');
var ref = require('@glencfl/ref-napi-di')(refBinding);
var ffiBinding = require('@glencfl/ffi-napi-binding');
var ffi = require('@glencfl/ffi-napi-di')(ref, ffiBinding);

var libm = ffi.Library('libm', {
  'ceil': [ 'double', [ 'double' ] ]
});
libm.ceil(1.5); // 2

// You can also access just functions in the current process by passing a null
var current = ffi.Library(null, {
  'atoi': [ 'int', [ 'string' ] ]
});
current.atoi('1234'); // 1234

V8 and 64-bit Types

Internally, V8 stores integers that will fit into a 32-bit space in a 32-bit integer, and those that fall outside of this get put into double-precision floating point numbers. This is problematic because FP numbers are imprecise. To get around this, the methods in node-ffi that deal with 64-bit integers return strings and can accept strings as parameters.

Call Overhead

There is non-trivial overhead associated with FFI calls. Comparing a hard-coded binding version of strtoul() to an FFI version of strtoul() shows that the native hard-coded binding is orders of magnitude faster. So don't just use the C version of a function just because it's faster. There's a significant cost in FFI calls, so make them worth it.

License

MIT License. See the LICENSE file.