xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

Node.js Native Addons All In One

Node.js Native Addons All In One

Node.js Native Addons/Node.js 原生扩展插件, 是指用 C / C++ 等底层语言编写的模块,然后通过 Node.js 提供的接口编译成可被 JavaScript 直接调用的扩展插件。

C++ Addons

Addons are dynamically-linked shared objects that can be loaded via the require() function as ordinary Node.js modules.
Addons provide a foreign function interface between JavaScript and native code.

There are three options for implementing addons:

  1. Node-API (recommended ✅)
  2. nan (Native Abstractions for Node.js)
  3. direct use of internal V8, libuv, and Node.js libraries

https://nodejs.org/api/addons.html

Node-API

Node-API(原名 N-API)是一个用于构建原生插件的 API。它独立于底层 JavaScript 运行时(例如 V8),并作为 Node.js 的一部分进行维护。
该 API 将在各个 Node.js 版本之间保持应用程序二进制接口 (ABI) 的稳定性。
其目的是使插件免受底层 JavaScript 引擎变更的影响,并允许为某一主要版本编译的模块无需重新编译即可在后续的 Node.js 主要版本上运行。ABI 稳定性指南提供了更详细的解释。

https://nodejs.org/api/n-api.html

Node-API is a stable C API built into Node.js that lets C/C++ code create, read, and manipulate JavaScript values as if they were created by JavaScript itself.
It was introduced experimentally in Node.js 8.0.0 and became stable (no longer behind a flag) in the Node.js 8/10 timeframe.

Because Node-API is part of Node.js itself, it requires no additional installation.

image
image

https://nodejs.org/learn/node-api

https://nodejs.org/zh-cn/learn/node-api

Node-API 的一个重要搭档是 npm 包 node-addon-api。
它将 C API 封装在一个符合 C++ 惯用语的 C++ 对象模型中,减少了样板代码,并使一些常见模式(例如将 C++ 对象封装成 JavaScript 对象)更加符合人体工程学。
它保留了 Node-API 的全部 ABI 稳定性保证。

$ npm i node-addon-api

https://www.npmjs.com/package/node-addon-api

https://github.com/nodejs/node-addon-api

NAN

Native Abstractions for Node.js / Node.js 的原生抽象

https://github.com/nodejs/nan

demos

// the equivalent of the following JavaScript code
module.exports.hello = () => 'world';

hello.cc

#include <node.h>

namespace demo {

  using v8::FunctionCallbackInfo;
  using v8::Isolate;
  using v8::Local;
  using v8::NewStringType;
  using v8::Object;
  using v8::String;
  using v8::Value;

  void Method(const FunctionCallbackInfo<Value>& args) {
    Isolate* isolate = args.GetIsolate();
    args.GetReturnValue().Set(String::NewFromUtf8(
        isolate, "world", NewStringType::kNormal).ToLocalChecked());
  }

  void Initialize(Local<Object> exports) {
    NODE_SET_METHOD(exports, "hello", Method);
  }

  // N.B.: no semi-colon, this is not a function
  NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize) 

}
// namespace demo


Makefile, hello.cc => > hello.node

NODEJS_DEV_ROOT ?= $(shell dirname "$(command -v node)")/..
CXXFLAGS = -std=c++23 -I$(NODEJS_DEV_ROOT)/include/node -fPIC -shared -Wl,-undefined,dynamic_lookup

# target source
hello.node: hello.cc
    $(CXX) $(CXXFLAGS) -o $@ $<

$ make
$ node -p 'require("./hello.node").hello()'
# world


(🐞 反爬虫测试!打击盗版⚠️)如果你看到这个信息, 说明这是一篇剽窃的文章,请访问 https://www.cnblogs.com/xgqfrms/ 查看原创文章!

.cpp vs .cc

.cpp 和 .cc 本质上没有语言层面的区别,只是 C++ 源文件的不同命名习惯。

image

  • C Plus Plus, .cpp
  • Google C++ Style Guide, .cc
$ g++ main.cpp
# or
$ g++ main.cc

CMake

image

C files → compiled with C compiler (e.g. gcc)
C++ files → compiled with C++ compiler (e.g. g++ / clang++)

node-gyp

https://www.npmjs.com/package/node-gyp

https://nodejs.org/learn/node-api/build-tools/node-gyp

fibonacci.cc

// The pure C++ function - fast, unmanaged, no JavaScript awareness.
int Fibonacci(int n) {
  if (n < 2) return n;
  return Fibonacci(n - 1) + Fibonacci(n - 2);
}

// The Bridge Function - This is where N-API works its art.
// It translates JavaScript arguments into C++ types, calls the function,
// and translates the C++ result back into a JavaScript value.
Napi::Value CalculateFibonacci(const Napi::CallbackInfo& info) {
  // The Napi::Env is our connection to the JavaScript world.
  Napi::Env env = info.Env();
  // 1. Validate the number of arguments
  if (info.Length() < 1) {
    Napi::TypeError::New(env, "Wrong number of arguments")
        .ThrowAsJavaScriptException();
    return env.Null();
  }
  // 2. Validate and convert the first argument to a C++ integer
  if (!info[0].IsNumber()) {
    Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
    return env.Null();
  }
  int n = info[0].As<Napi::Number>().Int32Value();
  // 3. Call our pure C++ function
  int result = Fibonacci(n);
  // 4. Convert the C++ integer back to a JavaScript Number and return it.
  return Napi::Number::New(env, result);
}

// The Init function - This is the entry point, called when the module is required.
// It defines what we expose to the JavaScript world.
Napi::Object Init(Napi::Env env, Napi::Object exports) {
  // Set the "calculate" property of the `exports` object to our bridge function.
  exports.Set(Napi::String::New(env, "calculate"),
              Napi::Function::New(env, CalculateFibonacci));
  return exports;
}

// This macro declares the entry point for the Node.js module.
NODE_API_MODULE(fibonacci, Init)

refs

image

image



©xgqfrms 2012-2021

www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2026-07-01 16:17  xgqfrms  阅读(24)  评论(7)    收藏  举报