NodeJs C++ addon(nan方式)

本文介绍如何使用 Native Abstractions for Node.js (nan) 库简化 Node.js 的 C++ 插件开发过程,包括基本函数和类的实现方法,并提供了一个完整的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • Native Abstractions for Node.js (nan)
  • nan方式的好处:使用nan方式,编写的c++插件接口,会自动兼容不同版本的nodejs
// nan 方式声明
static void New(const Nan::FunctionCallbackInfo<v8::Value>& info); // nan

// 6.x 版本兼容成类似如下接口
void hello(FunctionCallbackInfo<Value>& args); // 6.x
// .10.x 版本兼容成类似如下接口
Handle<Value> hello(const Arguments& args);    // 0.10.x
  • 因此,你的代码只需要随着 nan版本升级出现的改变而改变,至于Nodejs,nan会帮你兼容(前提是nan支持该版本的nodejs)
Hello World
  • hello.cpp
#include <nan.h>

void Method(const Nan::FunctionCallbackInfo<v8::Value>& info) {
    // 设置返回值
    info.GetReturnValue().Set(Nan::New("hello world").ToLocalChecked());
}
// 必须有一个Init函数
void Init(v8::Local<v8::Object> exports) {
    // 为exports追加hello方法  > 类似 nodejs中 exports.hello = xxxx;
    exports->Set(Nan::New("hello").ToLocalChecked(),
        Nan::New<v8::FunctionTemplate>(Method)->GetFunction());
}

// 固定写法
NODE_MODULE(hello, Init)
  • hello.js
var addon = require('./build/Release/hello.node');

console.log(addon.hello()); // 'hello world'
  • binding.gyp
{
  "targets": [
    {
      "target_name": "hello",
      "sources": [ "hello.cpp" ],
      "include_dirs": [
        "<!(node -e \"require('nan')\")"
      ]
    }
  ]
}
  • 准备编译环境( 在项目路径下)
  • npm install -g node-gyp (全局安装)
  • npm install nan
  • node-gyp configure (会产生build文件夹)
# 方式1
cd build
make
# 方式2
node-gype rebuild
  • node hello.js(执行)
类的写法
  • myobject.h(头文件)
#ifndef CLASS_H
#define CLASS_H

#include <nan.h>

class MyObject : public Nan::ObjectWrap {
 public:
  static void Init(v8::Local<v8::Object> exports);

 private:
  explicit MyObject(double value = 0);
  ~MyObject();
  // 类的成员函数
  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);
  static void GetValue(const Nan::FunctionCallbackInfo<v8::Value>& info);
  static void PlusOne(const Nan::FunctionCallbackInfo<v8::Value>& info);
  static void Multiply(const Nan::FunctionCallbackInfo<v8::Value>& info);
  static Nan::Persistent<v8::Function> constructor;
  double value_;
};

#endif // CLASS_H
  • myobject.cpp
 #include "myobject.h"
// 可以看成nodejs,使用的类的构造器
Nan::Persistent<v8::Function> MyObject::constructor;

MyObject::MyObject(double value) : value_(value) {
}

MyObject::~MyObject() {
}

void MyObject::Init(v8::Local<v8::Object> exports) {
  Nan::HandleScope scope;

  // 初始化构造函数模板
  v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
  tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  // 设置原型(此处将类的成员函数,设置到原型链上)
  Nan::SetPrototypeMethod(tpl, "value", GetValue);
  Nan::SetPrototypeMethod(tpl, "plusOne", PlusOne);
  Nan::SetPrototypeMethod(tpl, "multiply", Multiply);
  // 固定写法(设置构造器函数)
  constructor.Reset(tpl->GetFunction());
  exports->Set(Nan::New("MyObject").ToLocalChecked(), tpl->GetFunction());
}

void MyObject::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
  if (info.IsConstructCall()) {
    // 构造函数调用方式: `new MyObject(...)`
    double value = info[0]->IsUndefined() ? 0 : info[0]->NumberValue();
    MyObject* obj = new MyObject(value);
    obj->Wrap(info.This());
    info.GetReturnValue().Set(info.This());
  } else {
    //普通函数调用方式`MyObject(...)`
    const int argc = 1;
    v8::Local<v8::Value> argv[argc] = { info[0] };
    v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
    info.GetReturnValue().Set(cons->NewInstance(argc, argv));
  }
}

void MyObject::GetValue(const Nan::FunctionCallbackInfo<v8::Value>& info) {
  MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
  // 设置返回值
  info.GetReturnValue().Set(Nan::New(obj->value_));
}

void MyObject::PlusOne(const Nan::FunctionCallbackInfo<v8::Value>& info) {
  MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
  obj->value_ += 1;
  // 设置返回值
  info.GetReturnValue().Set(Nan::New(obj->value_));
}

void MyObject::Multiply(const Nan::FunctionCallbackInfo<v8::Value>& info) {
  MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
  double multiple = info[0]->IsUndefined() ? 1 : info[0]->NumberValue();

  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);

  const int argc = 1;
  v8::Local<v8::Value> argv[argc] = { Nan::New(obj->value_ * multiple) };
  // 此处类的对象(实例)
  info.GetReturnValue().Set(cons->NewInstance(argc, argv));
}
  • addon.cpp(相当于main.cpp)
#include <nan.h>
#include "myobject.h"

void InitAll(v8::Local<v8::Object> exports) {
  MyObject::Init(exports);
}

NODE_MODULE(addon, InitAll)
  • 调用 addon.js
var addon = require('./build/Release/addon.node');
var obj = new addon.MyObject(10);

console.log( obj.plusOne() ); // 11
console.log( obj.plusOne() ); // 12
console.log( obj.plusOne() ); // 13

console.log( obj.multiply().value() ); // 13
console.log( obj.multiply(10).value() ); // 130

var newobj = obj.multiply(-1);
console.log( newobj.value() ); // -13
console.log( obj === newobj ); // false
  • 编译方式同上(hello)
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值