阿西河

所有教程

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

我的收藏

    最近访问  (文章)

      教程列表

      抓包专区
      测试专区

      Node.js C++插件 传递包装的对象

      Node.js C++插件 传递包装的对象

      除了包装和返回 C++ 对象,也可以通过使用 Node.js 的辅助函数 node::ObjectWrap::Unwrap 进行去包装来传递包装的对象。 以下例子展示了一个 add() 函数,它可以把两个 MyObject 对象作为输入参数:

      // addon.cc
      #include <node.h>
      #include <node_object_wrap.h>
      #include "myobject.h"
      
      namespace demo {
      
      using v8::FunctionCallbackInfo;
      using v8::Isolate;
      using v8::Local;
      using v8::Number;
      using v8::Object;
      using v8::String;
      using v8::Value;
      
      void CreateObject(const FunctionCallbackInfo<Value>& args) {
        MyObject::NewInstance(args);
      }
      
      void Add(const FunctionCallbackInfo<Value>& args) {
        Isolate* isolate = args.GetIsolate();
      
        MyObject* obj1 = node::ObjectWrap::Unwrap<MyObject>(
            args[0]->ToObject());
        MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>(
            args[1]->ToObject());
      
        double sum = obj1->value() + obj2->value();
        args.GetReturnValue().Set(Number::New(isolate, sum));
      }
      
      void InitAll(Local< Object> exports) {
        MyObject::Init(exports->GetIsolate());
      
        NODE_SET_METHOD(exports, "createObject", CreateObject);
        NODE_SET_METHOD(exports, "add", Add);
      }
      
      NODE_MODULE(NODE_GYP_MODULE_NAME, InitAll)
      
      }  // namespace demo
      

      在 myobject.h 中,新增了一个新的公共方法用于在去包装对象后访问私有值。

      // 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::Isolate* isolate);
        static void NewInstance(const v8::FunctionCallbackInfo< v8::Value>& args);
        inline double value() const { return value_; }
      
       private:
        explicit MyObject(double value = 0);
        ~MyObject();
      
        static void New(const v8::FunctionCallbackInfo< v8::Value>& args);
        static v8::Persistent< v8::Function> constructor;
        double value_;
      };
      
      }  // namespace demo
      
      #endif
      

      myobject.cc 中的实现类似之前的例子:

      // myobject.cc
      #include <node.h>
      #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::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(Isolate* isolate) {
        // Prepare constructor template
        Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
        tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
        tpl->InstanceTemplate()->SetInternalFieldCount(1);
      
        constructor.Reset(isolate, 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> instance =
              cons->NewInstance(context, argc, argv).ToLocalChecked();
          args.GetReturnValue().Set(instance);
        }
      }
      
      void MyObject::NewInstance(const FunctionCallbackInfo<Value>& args) {
        Isolate* isolate = args.GetIsolate();
      
        const unsigned argc = 1;
        Local<Value> argv[argc] = { args[0] };
        Local< Function> cons = Local< Function>::New(isolate, constructor);
        Local<Context> context = isolate->GetCurrentContext();
        Local< Object> instance =
            cons->NewInstance(context, argc, argv).ToLocalChecked();
      
        args.GetReturnValue().Set(instance);
      }
      
      }  // namespace demo
      

      测试:

      // test.js
      const addon = require('./build/Release/addon');
      
      const obj1 = addon.createObject(10);
      const obj2 = addon.createObject(20);
      const result = addon.add(obj1, obj2);
      
      console.log(result);
      // 打印: 30
      

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


      目录
      本文目录
      目录