Bindings between Nim and N-API
These instructions will help you get up and running. Keep in mind this project is still in its infancy and may be incomplete or subject to change.
If you don't yet have Nim installed, please visit https://nim-lang.org/install.html
First of all, you will need to have Node installed with a version number no less than 8.0. N-API was introduced in this version and remains experimental.
napibuild is a program distributed as a binary in this project which attempts to automate the process of creating .node addons from a Nim project file.
napibuild depends on an npm package called node-gyp which can be installed via
npm install -g node-gypConsequently, node-gyp requires python 2.x, while version 2.7 is recommended. node-gyp has a few other OS-specific build essentials which are detailed here, but will likely work out-of-the-box on most systems.
To install this library and napibuild
git clone https://github.com/AjBreidenbach/napibindings.git
cd napibindings
nimble installEnter y and you're finished
To run all tests
cd test/
npm install
napibuild main.nim
node index.js
cd ../To view the documentation
nim doc napibindings.nim && google-chrome napibindings.html > /dev/null &
Start by running npm init and entering information as prompted
bindings is a useful package for loading native addons, it can be installed via npm install --save bindings
Loading addons compiled by node-gyp then becomes as simple as
const addon = require('bindings')('myNimProjectfile')Where the original Nim file myNimProjectfile.nim was compiled via
napibuild myNimProjectfile.nimIn myNimProjectfile.nim, the node module can be initialized by the following
import napibindings
init proc(exports: Module) =
exports.register("hello", "hello world!")The basic unit for N-API values is the type napi_value. They are wrapped such that they behave very similarly to the JsonNode type from the core Nim json module. They can be indexed via [] and []= and even support the % and %* marshalling operators.
register can be used to add Nim primitives and napi_values to a module's exports. Their use is rather straightforward.
fn and registerFn are templates which can be called
fn(2, myFunction):
return %(args[0].getInt + args[1].getInt)and ...
exports.registerFn(2, "myFunction"):
return %* {"first": args[0], "second": args[1]}respectively.
In the case of fn, myFunction is injected into the caller's scope, whereas registerFn would added to exports directly.
Both templates expose args of type seq[napi_value] which are the parameters passed through the JavaScript invocation and this of type napi_value which is identical to the JavaScript this global variable. Both templates are also able to return a napi_value or nil for undefined.
callFunction can be used as would be expected and has the following declaration
proc callFunction(fn: napi_value; args: openArray[napi_value] = []; this = %[]): napi_value {..}All contributions are welcome.
The goal of this project is to wrap all of the functionality of N-API as detailed here in a way that is ergonomic, performant, and idiomatic to Nim.
The entirety of the API can presently be imported in Nim when compiling with napibuild via the pragma header: "<node_api.h>" and is not terribly difficult to work with.
In the future, napibuild should either be expanded to allow for more build flexibility and gyp functionality or faded out in favor of build tools preferred by the Nim community.