美文网首页
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