美文网首页
Nodejs插件-Demo解读

Nodejs插件-Demo解读

作者: 陈道乐 | 来源:发表于2018-11-18 23:30 被阅读0次

1.对象封装

#include "myobject.h"
#include <assert.h>

napi_ref MyObject::constructor;

MyObject::MyObject(double value)
    : value_(value), env_(nullptr), wrapper_(nullptr) {}

//4. 析构函数,解除持久化引用
MyObject::~MyObject() { napi_delete_reference(env_, wrapper_); }

// 3. Js对象销毁时,调用的方法
void MyObject::Destructor(napi_env env, void* nativeObject, void* /*finalize_hint*/) {
  reinterpret_cast<MyObject*>(nativeObject)->~MyObject();
}

#define DECLARE_NAPI_METHOD(name, func)                          \
  { name, 0, func, 0, 0, 0, napi_default, 0 }

//1.该静态方法在js进行require操作时,调用
napi_value MyObject::Init(napi_env env, napi_value exports) {
  napi_status status;
//定义对象的方法和参数对象
  napi_property_descriptor properties[] = {
      { "value", 0, 0, GetValue, SetValue, 0, napi_default, 0 },
      DECLARE_NAPI_METHOD("plusOne", PlusOne),
      DECLARE_NAPI_METHOD("multiply", Multiply),
  };

  napi_value cons;
//创建对象结构
  status =
      napi_define_class(env, "MyObject", NAPI_AUTO_LENGTH, New, nullptr, 3, properties, &cons);
  assert(status == napi_ok);

//通过引用,来对对象结构进行持久化保存
  status = napi_create_reference(env, cons, 1, &constructor);
  assert(status == napi_ok);

//将对象结构挂载到exports上,对外暴露
  status = napi_set_named_property(env, exports, "MyObject", cons);
  assert(status == napi_ok);

//返回exports
  return exports;
}

//2.该方法在对外暴露的对象结构中的方法被调用时,或者使用对象结构创建一个新的实例时。
napi_value MyObject::New(napi_env env, napi_callback_info info) {
  napi_status status;

  napi_value target;
//该方法判断是否通过 new target 的方式创建对象
  status = napi_get_new_target(env, info, &target);
  assert(status == napi_ok);
  bool is_constructor = target != nullptr;

  if (is_constructor) {
    // 以new target 的方式创建实例对象
    size_t argc = 1;
    napi_value args[1];
    napi_value jsthis;
//获取创建时的参数
    status = napi_get_cb_info(env, info, &argc, args, &jsthis, nullptr);
    assert(status == napi_ok);

    double value = 0;

    napi_valuetype valuetype;
//判断参数类型
    status = napi_typeof(env, args[0], &valuetype);
    assert(status == napi_ok);

    if (valuetype != napi_undefined) {
      status = napi_get_value_double(env, args[0], &value);
      assert(status == napi_ok);
    }
    
  //创建实例对象
    MyObject* obj = new MyObject(value);

    obj->env_ = env;
//使用实例后的对象进行封装,封装成js可调用的对象,并使用引用进行持久化保存,这个方法与napi_new_instance 类似, 但是napi_wrap并没有对对象进行执持久化处理, 这也是new target 的区别
    status = napi_wrap(env,
                       jsthis,
                       reinterpret_cast<void*>(obj), //对象销毁时,调用的方法
                       MyObject::Destructor,
                       nullptr,  // finalize_hint
                       &obj->wrapper_);
    assert(status == napi_ok);
//返回封装后的实例
    return jsthis;
  } else {
    // 不实例化对象,直接调用对象方法
    size_t argc_ = 1;
    napi_value args[1];
  //获取参数
    status = napi_get_cb_info(env, info, &argc_, args, nullptr, nullptr);
    assert(status == napi_ok);

    const size_t argc = 1;
    napi_value argv[argc] = {args[0]};

    napi_value cons;
   //参数类型判断
    status = napi_get_reference_value(env, constructor, &cons);
    assert(status == napi_ok);

    napi_value instance;
   //创建一个零时实例对象
    status = napi_new_instance(env, cons, argc, argv, &instance);
    assert(status == napi_ok);
    // 返回临时的对象,该对象在使用完成后,就立即销毁了
    return instance;
  }
}

//5. 取值操作
napi_value MyObject::GetValue(napi_env env, napi_callback_info info) {
  napi_status status;

  napi_value jsthis;
  //获取js实例
  status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr);
  assert(status == napi_ok);

  MyObject* obj;
  //使用js的实例来获取C++实例对象,
  status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));
  assert(status == napi_ok);

  napi_value num;
  //创建js数据类型
  status = napi_create_double(env, obj->value_, &num);
  assert(status == napi_ok);

  //返回js调用结果
  return num;
}

//6. 设置操作
napi_value MyObject::SetValue(napi_env env, napi_callback_info info) {
  napi_status status;

  size_t argc = 1;
  napi_value value;
  napi_value jsthis;
  status = napi_get_cb_info(env, info, &argc, &value, &jsthis, nullptr);
  assert(status == napi_ok);


  MyObject* obj;
  status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));
  assert(status == napi_ok);

  status = napi_get_value_double(env, value, &obj->value_);
  assert(status == napi_ok);

  return nullptr;
}

//7.递增加1操作
napi_value MyObject::PlusOne(napi_env env, napi_callback_info info) {
  napi_status status;

  napi_value jsthis;
  status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, nullptr);
  assert(status == napi_ok);

  MyObject* obj;
  status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));
  assert(status == napi_ok);

  obj->value_ += 1;

  napi_value num;
  status = napi_create_double(env, obj->value_, &num);
  assert(status == napi_ok);

  return num;
}

//8,该方法直接对value进行操作,而且返回一个零时对象
napi_value MyObject::Multiply(napi_env env, napi_callback_info info) {
  napi_status status;

  size_t argc = 1;
  napi_value args[1];
  napi_value jsthis;
  status = napi_get_cb_info(env, info, &argc, args, &jsthis, nullptr);
  assert(status == napi_ok);

  napi_valuetype valuetype;
  status = napi_typeof(env, args[0], &valuetype);
  assert(status == napi_ok);

  double multiple = 1;
  if (valuetype != napi_undefined) {
    status = napi_get_value_double(env, args[0], &multiple);
    assert(status == napi_ok);
  }

  MyObject* obj;
  //使用js实例获取C++实例对象
  status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));
  assert(status == napi_ok);

  napi_value cons;
  //此处挺有意思,使用引用constructor获取对象结构
  status = napi_get_reference_value(env, constructor, &cons);
  assert(status == napi_ok);

  const int kArgCount = 1;
  napi_value argv[kArgCount];
  //创建js数据类型
  status = napi_create_double(env, obj->value_ * multiple, argv);
  assert(status == napi_ok);

  napi_value instance;
  //创建零时js对象
  status = napi_new_instance(env, cons, kArgCount, argv, &instance);
  assert(status == napi_ok);

  //返回创建对象
  return instance;
}
使用
var addon = require('bindings')('addon');

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

相关文章

网友评论

      本文标题:Nodejs插件-Demo解读

      本文链接:https://www.haomeiwen.com/subject/unenfqtx.html