N-API Intro

https://stackoverflow.com/questions/36766696/which-is-correct-node-js-architecture

napi_value Init (napi_env env, napi_value exports) {
  napi_status status;
  napi_property_descriptor desc[] = {
    {"calculate", NULL, Fibonacci, NULL, NULL, NULL, napi_default, NULL},
    {"sum", NULL, Sum, NULL, NULL, NULL, napi_default, NULL}
  };
  status = napi_define_properties(env, exports, 2, desc);

  if (status != napi_ok) {
    napi_throw_error(env, NULL, "Unable to wrap native function");
  }

  return exports;
}

NAPI_MODULE(fibonacci, Init);

NAPI_MODULE(MODULE_NAME, CONSTRUCTOR);

typedef enum {
  // ES6 types (corresponds to typeof)
  napi_undefined,
  napi_null,
  napi_boolean,
  napi_number,
  napi_string,
  napi_symbol,
  napi_object,
  napi_function,
  napi_external,
  napi_bigint,
} napi_valuetype;
typedef struct {
  // One of utf8name or name should be NULL.
  const char* utf8name;
  napi_value name;

  napi_callback method;
  napi_callback getter;
  napi_callback setter;
  napi_value value;

  napi_property_attributes attributes;
  void* data;
} napi_property_descriptor;
typedef enum {
  napi_default = 0,
  napi_writable = 1 << 0,
  napi_enumerable = 1 << 1,
  napi_configurable = 1 << 2,
  napi_static = 1 << 10,
} napi_property_attributes;

CPP Method

JS Fn Name

napi_property_descriptor desc[] = {
  {"calculate", NULL, Fibonacci, NULL, NULL, NULL, napi_default, NULL},
  {"sum", NULL, Sum, NULL, NULL, NULL, napi_default, NULL}
};
napi_status napi_define_properties(napi_env env,
                                   napi_value object,
                                   size_t property_count,
                                   const napi_property_descriptor* properties);
status = napi_define_properties(env, exports, 2, desc);
napi_value Fibonacci (napi_env env, napi_callback_info info) {
  napi_status status;
  size_t argc = 1;
  napi_value argv[1];
  int times = 0;
  unsigned long long int nowNum = 0;
  unsigned long long int lastNum = 1;
  unsigned long long int lastLastNum = 0;

  status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);

  if (status != napi_ok) {
    napi_throw_error(env, NULL, "Failed to parse arguments");
  }

  status = napi_get_value_int32(env, argv[0], &times);

  if (status != napi_ok) {
    napi_throw_error(env, NULL, "Invalid number was passed as argument");
  }

  napi_value result;

  for (int i = 1; i < times; i++) {
    nowNum = lastNum + lastLastNum;
    lastLastNum = lastNum;
    lastNum = nowNum;
  }

  status = napi_create_int64(env, nowNum, &result);

  if (status != napi_ok) {
    napi_throw_error(env, NULL, "Unable to create return value");
  }

  return result;
}
napi_status napi_get_cb_info(napi_env env,
                             napi_callback_info cbinfo,
                             size_t* argc,
                             napi_value* argv,
                             napi_value* thisArg,
                             void** data)

Copy [argc] size arguments into

size_t argc = 1;
napi_value argv[1];

status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
napi_status napi_get_value_int32(napi_env env,
                                 napi_value value,
                                 int32_t* result)
int times = 0;
status = napi_get_value_int32(env, argv[0], &times);

if (status != napi_ok) {
  napi_throw_error(env, NULL, "Invalid number was passed as argument");
}
int times = 0;
unsigned long long int nowNum = 0;
unsigned long long int lastNum = 1;
unsigned long long int lastLastNum = 0;
napi_value result;

for (int i = 1; i < times; i++) {
  nowNum = lastNum + lastLastNum;
  lastLastNum = lastNum;
  lastNum = nowNum;
}
napi_status napi_create_int64(napi_env env, int64_t value, napi_value* result)
napi_value result;

// Calculating...

status = napi_create_int64(env, nowNum, &result);

if (status != napi_ok) {
  napi_throw_error(env, NULL, "Unable to create return value");
}

return result;

binding.gyp

{
    "targets": [{
        "target_name": "fibonacci",
        "sources": [ "./fibonacci.cc" ]
    }]
}

node-gyp rebuild

npm i -g node-gyp

app.js

const fibonacci = require('./build/Release/fibonacci');
const size = 90;

const result = fibonacci.calculate(size);

let nowNum = 0;
let lastNum = 1;
let lastLastNum = 0;

for (let i = 1; i < size; i += 1) {
  nowNum = lastNum + lastLastNum;
  lastLastNum = lastNum;
  lastNum = nowNum;
}

console.log(result);
console.log(nowNum);

const sumTimes = 130000000;

const sumResult = fibonacci.sum(sumTimes);

let sum = 0;

for (let i = 0; i < sumTimes; i += 1) {
  sum += i;
}

console.log(sumResult);
console.log(sum);

https://github.com/fantasywind/N-API-Sample

NAPI Intro

By Chia Yu Pai

NAPI Intro

  • 360