Image suorce: Rainbow Colors Electronic
Foreign Function Interface Adapter Powered by Decorator & TypeScript
- Binding shared library(
.dll
/.so
/.dylib
) to a TypeScript class by decorators. - Support
async
mode when a class method defined with a return type ofPromise
. - Supports Windows(
.dll
), Linux(.so
), and MacOS(.dylib
). - The class will be forced singleton.
- Node.js v10 or v11 for ffi (neither v12 nor v13, see #554)
- TypeScript with
--target ES5
,--experimentalDecorators
, and--emitDecoratorMetadata
options on.
Background:
- We have a shared library file
libfactorial.so
(.dll
/.dylib
as well) - the library has a function
uint64_t factorial(int)
- We want to use
factorial()
in TypeScript.
import {
LIBRARY,
API,
RETURN,
} from 'ffi-adapter'
@LIBRARY('./libfactorial')
export class LibFactorial {
@API() factorial (n: number): number { return RETURN(n) }
}
const lib = new LibFactorial()
console.log('factorial(5) =', lib.factorial(5))
// Output: factorial(5) = 120
That's it! Use it is that easy!
import {
LIBRARY,
API,
RETURN,
} from 'ffi-adapter'
All you need is the above two decorators and one function:
LIBRARY(libraryFile: string)
- Class decoratorAPI(returnType?: FfiReturnType)
- Method decoratorRETURN(...args: any[])
- Method need to return this function to confirm the adapting.
libraryFile
:string
- The shared library file path, which will be adapted and binding to the class.
@LIBRARY('./libfactorial')
class LibFactorial { /* ... */ }
returnType
:FfiReturnType
- Optional. Specify the library function return type. Can be refered automatically by the TypeScript if the method return is not aPromise
.
Specific the library function return type, and bind the same name function from library to the decorated class method.
@API('uint64') factorial(n: number): Promise<number> { ... }
args
:any[]
- The method args. Just place every args of the method, to th RETURN function.
@API() factorial(...args: any[]) { return RETURN(...args) }
The actual return value will be take care by the @API
decorator.
Credit: https://github.com/node-ffi/node-ffi/tree/master/example/factorial
#include <stdint.h>
#if defined(WIN32) || defined(_WIN32)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
EXPORT uint64_t factorial(int max) {
int i = max;
uint64_t result = 1;
while (i >= 2) {
result *= i--;
}
return result;
}
gcc -dynamiclib -undefined suppress -flat_namespace factorial.c -o libfactorial.dylib
gcc -shared -fpic factorial.c -o libfactorial.so
2.3 To compile libfactorial.dll
on Windows (http://stackoverflow.com/a/2220213)
cl.exe /D_USRDLL /D_WINDLL factorial.c /link /DLL /OUT:libfactorial.dll
Save the following code to file lib-factorial.ts
:
import {
LIBRARY,
API,
RETURN,
} from 'ffi-adapter'
@LIBRARY('./libfactorial')
export class LibFactorial {
@API() factorial (n: number): number { return RETURN(n) }
}
import { LibFactorial } from './lib-factorial.ts'
const lib = new LibFactorial()
console.log('factorial(5) =', lib.factorial(5))
// Output: factorial(5) = 120
You will agree with me that it's super clean, beautiful, and easy to maintain! ;-)
- TypeScript - Class Decorators
- Generate ffi bindings from header files
- node-ffi使用指南
- Node FFI Tutorial
- Use the Microsoft C++ toolset from the command line - To open a developer command prompt window
- FFI Definitions of Windows win32 api for node-ffi-napi
- Decorators & metadata reflection in TypeScript: From Novice to Expert - PART IV: Types serialization & The metadata reflection API
- decorator metadata is emitted only on decorated members
Support all Node.js versions (10/11/12/13/14/15/16) now!
The first version.
- Use
@LIBRARY()
,@API()
, andRETURN()
as decorators to bind a shared library to a TypeScript Class.
- Code & Docs © 2020-now Huan LI <zixia@zixia.net>
- Code released under the Apache-2.0 License
- Docs released under Creative Commons