Giter Club home page Giter Club logo

node-bindgen's Introduction

node-bindgen

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

Features

  • Easy: Just write idiomatic Rust code, node-bindgen take care of generating Node.js FFI wrapper codes.
  • Safe: Node.js arguments are checked automatically based on Rust types.
  • Async: Support Async Rust. Async codes are translated into Node.js promises.
  • Class: Rust struct can be accessed using Node.js classes.
  • Stream: Implement Node.js stream using Rust
  • N-API: Use Node.js N-API, which means you don't have to recompile your module.

Compatibility with Node.js version

This project uses the v7 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 boilerplate code. Node-bindgen generates external "C" glue code from rust code, including native module registration. node-bindgen make it writing node-js module easy and fun.

Getting started

CLI Installation

Install nj-cli command line, which will be used to generate the 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 a regular dependency (as below):

[dependencies]
node-bindgen = { version = "4.0" }

Then add node-bindgen's procedure macro to your build-dependencies as below:

[build-dependencies]
node-bindgen = { version = "4.0", features = ["build"] }

Then update crate type to cdylib to generate node.js compatible native module:

[lib]
crate-type = ["cdylib"]

Finally, add build.rs at the top of the project with following content:

fn main() {
    node_bindgen::build::configure();
}

Example

Here is a function that adds two numbers. Note that you don't need to worry about JS conversion.

use node_bindgen::derive::node_bindgen;

/// 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.

To build a release version:

nj-cli build --release

Watching ./src for Changes

While developing your native module, you may want to watch for file changes and run a command when a change occurs, for example cargo check or cargo build.

For this, we can use nj-cli watch.

nj-cli watch installs [if it does not exist] and passes arguments to cargo watch. By default, nj-cli watch will run cargo check against your ./src files.

To see all available methods for nj-cli watch, run the following command:

nj-cli watch -- --help

Using in Node.js

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

$ 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

#[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

#[node_bindgen]
fn sum(first: i32, second: Option<i32>) -> i32 {
    first + second.unwrap_or(0)
}

Then sum can be invoked as sum(10) or sum(10,20)

Callback

JS callback are mapped as Rust closure.

#[node_bindgen]
fn hello<F: Fn(String)>(first: f64, second: F) {

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

    second(msg);
}

from node:

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.

use std::time::Duration;
use flv_future_aio::time::sleep;
use node_bindgen::derive::node_bindgen;


#[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
}
let addon = require('./dist');

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

JavaScript class

JavaScript class is supported.

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
    }
}
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.

Windows + Electron Support

When using node-bindgen with electron on Windows, nj-build must compile a C++ file, win_delay_load_hook.cc, and therefore it is required that the development environment has a valid C/C++ compiler.

If your machine does not have a valid C/C++ compiler, install Microsoft VSCode.

In the future, this file will be re-written in Rust, removing this dependency.

Contributing

If you'd like to contribute to the project, please read our Contributing guide.

License

This project is licensed under the Apache license.

node-bindgen's People

Contributors

ajhunyady avatar danielhenrymantilla avatar dependabot[bot] avatar federico-terzi avatar garyhai avatar mattcollier avatar nicholastmosher avatar nickbabcock avatar palfrey avatar ryanmtate avatar sehz avatar simlay avatar usagi avatar vijaylaxmid avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.