Linker.js is a foreign function interface for Node.js. Linker.js is part of Concurrent.js.
Important Note: Current version of Linker.js is only compatible with Linux-based operating systems.
- Language support
- C, C++, Go, Rust or any language that can produce C-shared libraries (via C Linker)
- Java
- Python (via Python Linker)
- Ruby
- Build upon the Node-API, libffi and Python C-API libraries
- Supports zero-copy data passing through buffers
- Automatically collects the buffers memories
- Has a minimal API
sudo apt -y install build-essential cmake
npm i -D cmake-js
npm i @bitair/linker.js
C linker provides the interface for accessing any C-shared libraries. Accessing C, C++, Go, and Rust libraries has been covered in the usage section.
sudo apt -y install libffi-dev
npx linker.js install c_linker
index.js
const { link, ReturnType } = require('@bitair/linker.js')
const libPath = __dirname + '/lib.so'
const { add } = link(libPath, {
add: ReturnType.Number
})
console.log(add(5, 3))
lib.c
double add(double a, double b) {
return a + b;
}
build.sh
gcc -c -fPIC lib.c && gcc -shared -o lib.so lib.o
lib.cpp
double cpp_add(double a, double b)
{
return a + b;
}
extern "C"
{
double add(double a, double b)
{
return cpp_add(a, b);
}
}
build.sh
gcc -c -fPIC lib.cpp && gcc -shared -o lib.so lib.o
lib.go
package main
import "C"
func go_add(x float64, y float64) float64 {
return x + y
}
//export add
func add(x C.double, y C.double) C.double {
return C.double(go_add(float64(x), float64(y)))
}
func main() {}
build.sh
go build -o lib.so -buildmode=c-shared lib.go
lib.rs
use libc::c_double;
fn rs_add(a: f64, b: f64) -> f64 {
a + b
}
#[no_mangle]
pub extern "C" fn add(a: c_double, b: c_double) -> c_double {
return rs_add(a, b);
}
Cargo.toml
[lib]
crate-type = ["cdylib"]
[dependencies]
libc = "0.2"
build.sh
cargo build
Please see the test folder for a complete sample code.
Python linker provides the interface for accessing python libraries.
sudo apt -y install python3-dev
npx linker.js install py_linker
index.js
const { link, ReturnType } = require('@bitair/linker.js')
const libPath = __dirname + '/lib.py'
const { add } = link(libPath, {
add: ReturnType.Number
})
console.log(add(5, 3))
lib.py
def add(a, b):
return float(a + b)
Please see the test folder for a complete sample code.
link(libPath: string, functions: SignatureDict): Proxy
Links to a shared library and returns a proxy for accessing its functions.
-
libPath: string
Path of the shared library.
-
functions: SignatureDict
Signatures of the foreign functions. Note that the types of a function parameters will be inferred at the call time from the passing arguments.
type SignatureDict = { [key: string]: ReturnType }
-
key: string
Name of the foreign function.
-
ReturnType
Type of the return value.
enum ReturnType { ArrayBuffer, Boolean, Number, String }
-
-
Proxy
type Proxy = { [key: string]: (...params: unknown[]) => unknown }
-
key: string
Name of the foreign function.
-
(...params:unknown[]) => unknown
The function's invoker.
-
JS | C | Python |
---|---|---|
ArrayBuffer | struct Buffer | memoryview |
boolean | bool | bool |
number | double | float |
string (UTF-8) | char * | str |
typedef struct {
void* data;
size_t len;
} Buffer;
Notes:
- Strings, booleans, and numbers are shared by value between JavaScript and a foreign function.
- ArrayBuffers/Buffers are shared by reference. Their allocated memories will be automatically released once their JavaScript consumer is out of scope.
- A string that's returned from a C function must be dynamically allocated. The allocated memory will be automatically released once the string has been passed to JavaScript.