阿西河

所有教程

公众号
🌙
阿西河前端的公众号

我的收藏

    最近访问  (文章)

      教程列表

      抓包专区
      测试专区

      Node.js C++插件 包装 C++ 对象

      Node.js C++插件 包装 C++ 对象

      也可以包装 C++ 对象/类使其可以使用 JavaScript 的 new 操作来创建新的实例:

      // addon.cc
      #include <node.h>
      #include "myobject.h"
      
      namespace demo {
      
      using v8::Local;
      using v8::Object;
      
      void InitAll(Local< Object> exports) {
        MyObject::Init(exports);
      }
      
      NODE_MODULE(NODE_GYP_MODULE_NAME, InitAll)
      
      }  // namespace demo
      

      然后,在 myobject.h 中,包装类继承自 node::ObjectWrap:

      // myobject.h
      #ifndef MYOBJECT_H
      #define MYOBJECT_H
      
      #include <node.h>
      #include <node_object_wrap.h>
      
      namespace demo {
      
      class MyObject : public node::ObjectWrap {
       public:
        static void Init(v8::Local< v8::Object> exports);
      
       private:
        explicit MyObject(double value = 0);
        ~MyObject();
      
        static void New(const v8::FunctionCallbackInfo< v8::Value>& args);
        static void PlusOne(const v8::FunctionCallbackInfo< v8::Value>& args);
        static v8::Persistent< v8::Function> constructor;
        double value_;
      };
      
      }  // namespace demo
      
      #endif
      

      在 myobject.cc 中,实现要被开放的各种方法。 下面,通过把 plusOne() 添加到构造函数的原型来开放它:

      // myobject.cc
      #include "myobject.h"
      
      namespace demo {
      
      using v8::Context;
      using v8::Function;
      using v8::FunctionCallbackInfo;
      using v8::FunctionTemplate;
      using v8::Isolate;
      using v8::Local;
      using v8::Number;
      using v8::Object;
      using v8::Persistent;
      using v8::String;
      using v8::Value;
      
      Persistent< Function> MyObject::constructor;
      
      MyObject::MyObject(double value) : value_(value) {
      }
      
      MyObject::~MyObject() {
      }
      
      void MyObject::Init(Local< Object> exports) {
        Isolate* isolate = exports->GetIsolate();
      
        // 准备构造函数模版
        Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
        tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
        tpl->InstanceTemplate()->SetInternalFieldCount(1);
      
        // 原型
        NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
      
        constructor.Reset(isolate, tpl->GetFunction());
        exports->Set(String::NewFromUtf8(isolate, "MyObject"),
                     tpl->GetFunction());
      }
      
      void MyObject::New(const FunctionCallbackInfo<Value>& args) {
        Isolate* isolate = args.GetIsolate();
      
        if (args.IsConstructCall()) {
          // 像构造函数一样调用:`new MyObject(...)`
          double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
          MyObject* obj = new MyObject(value);
          obj->Wrap(args.This());
          args.GetReturnValue().Set(args.This());
        } else {
          // 像普通方法 `MyObject(...)` 一样调用,转为构造调用。
          const int argc = 1;
          Local<Value> argv[argc] = { args[0] };
          Local<Context> context = isolate->GetCurrentContext();
          Local< Function> cons = Local< Function>::New(isolate, constructor);
          Local< Object> result =
              cons->NewInstance(context, argc, argv).ToLocalChecked();
          args.GetReturnValue().Set(result);
        }
      }
      
      void MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {
        Isolate* isolate = args.GetIsolate();
      
        MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.Holder());
        obj->value_ += 1;
      
        args.GetReturnValue().Set(Number::New(isolate, obj->value_));
      }
      
      }  // namespace demo
      

      要构建这个例子, myobject.cc 文件必须被添加到 binding.gyp:

      {
        "targets": [
          {
            "target_name": "addon",
            "sources": [
              "addon.cc",
              "myobject.cc"
            ]
          }
        ]
      }
      

      测试:

      // test.js
      const addon = require('./build/Release/addon');
      
      const obj = new addon.MyObject(10);
      console.log(obj.plusOne());
      // 打印: 11
      console.log(obj.plusOne());
      // 打印: 12
      console.log(obj.plusOne());
      // 打印: 13
      

      更多内容请参考:Node.js C++插件,或者通过 点击对应菜单 进行查看;


      目录
      本文目录
      目录