node-bindgen

Easy way to write native Node.js module using idiomatic Rust


CI Status Crates.io version Download docs.rs docs chat

Features

Compatibility with Node.js version

This project uses v5 of Node N-API. Please see following compatibility matrix.

Following OS are supported: * Linux * MacOs * Windows

Why node-bindgen?

Writing native node-js requires lots of boiler plate code. Node-bindgen generates external "C" glue code from rust code including native module registration. This make it writing node-js module easy and fun.

Node-bi

Getting started

CLI Installation

Install nj-cli command line which will be used to generate native library.

cargo install nj-cli

This is one time step.

Configuring Cargo.toml

Add two dependencies to your projects' Cargo.toml.

Add node-bindgen as as regular dependencies as below: [dependencies] node-bindgen = { version = "2.0.0-beta.1" }

Then add node-bindgen's procedure macro to your build-dependencies as below: [build-dependencies] node-bindgen = { path = "../../", features = ["build"] }

Then update crate type to cdylib to generate node.js compatible native module: [lib] crate-type = ["cdylib"]

Example

A simple functional example which add two integers. Noticed that you don't need to worry about JS conversion.

```rust

use nodebindgen::derive::nodebindgen;

/// add two integer

[node_bindgen]

fn sum(first: i32, second: i32) -> i32 {
first + second }

```

Building native library

To build node.js library, using nj-cli to build:

nj-cli build

This will generate Node.js module in "./dist" folder.

Using in Node.js

Then in the Node.js, rust function can invoked as normal node.js function:

```js $ node Welcome to Node.js v14.0.0. Type ".help" for more information.

let addon = require('./dist'); undefined addon.sum(2,3) 5

```

Features

Function name or method can be renamed instead of default mapping

```rust

[node_bindgen(name="multiply")]

fn mul(first: i32,second: i32) -> i32 {
first * second } ```

Rust function mul is re-mapped as multiply

Optional argument

Argument can be skipped if it is marked as optional ```rust

[node_bindgen]

fn sum(first: i32, second: Option) -> i32 {
first + second.unwrap_or(0) } Then sum can be invoked as sum(10)orsum(10,20)```

Callback

JS callback are mapped as Rust closure

```rust

[node_bindgen]

fn hello

let msg = format!("argument is: {}", first);

second(msg);

} ```

from node:

```js let addon = require('./dist');

addon.hello(2,function(msg){ assert.equal(msg,"argument is: 2"); console.log(msg); // print out argument is 2 }); ```

Callback are supported in Async rust as well.

Support for Async Rust

Async rust function is mapped to Node.js promise.

```rust

use std::time::Duration; use flvfutureaio::time::sleep; use nodebindgen::derive::nodebindgen;

[node_bindgen]

async fn hello(arg: f64) -> f64 { println!("sleeping"); sleep(Duration::from_secs(1)).await; println!("woke and adding 10.0"); arg + 10.0 } ```

```js let addon = require('./dist');

addon.hello(5).then((val) => { console.log("future value is %s",val); });

```

JavaScript class

JavaScript class is supported.

```rust

struct MyClass { val: f64, }

[node_bindgen]

impl MyClass {

#[node_bindgen(constructor)]
fn new(val: f64) -> Self {
    Self { val }
}

#[node_bindgen]
fn plus_one(&self) -> f64 {
    self.val + 1.0
}

#[node_bindgen(getter)]
fn value(&self) -> f64 {
    self.val
}

} ```

```js let addon = require('./dist'); const assert = require('assert');

let obj = new addon.MyObject(10); assert.equal(obj.value,10,"verify value works"); assert.equal(obj.plusOne(),11); ```

There are more features in the examples folder