• Node Addon


    Node Addon as bridge between javascript and C++

    #include <node.h>
    
    namespace HelloWorldDemo {
      using v8::FunctionCallbackInfo;  //used for passing arguments and returning val 
      using v8::Isolate;               //v8 VM which has memory heap
      using v8::Local;                 //Local is template of handle, Local<ClassType> means handle of ClassType
      using v8::Object;
      using v8::String;
      using v8::Value;
      using v8::Null;
      using v8::Number;
      using v8::Function;
      using v8::Exception;
      using v8::FunctionTemplate;
      
      //hello method
      void hello (const FunctionCallbackInfo<Value>& args) {
        
        //get v8 VM
        Isolate* isolate = args.GetIsolate();
        
        //create js string "hello world" in v8 VM heap
        args.GetReturnValue().Set(String::NewFromUtf8(isolate, "hello world."));
      }
    
      //accumulate method
      void accumulate (const FunctionCallbackInfo<Value>& args) {
        Isolate* isolate = args.GetIsolate();
            
        /*throw exception*/
        if (args.Length() < 1) {
          isolate->ThrowException(Exception::TypeError(
            String::NewFromUtf8(isolate, "Arguments Number Error.")
          ));
          return;
        }
    
        /*throw exception*/
        if (!args[args.Length() - 1]->IsFunction()) {
          isolate->ThrowException(Exception::TypeError(
            String::NewFromUtf8(isolate, "No Callback Error.")
          ));
          return;
        }
        
        //get callback function from js
        Local<Function> callback = Local<Function>::Cast(args[args.Length() - 1]);
        
        //accumulate
        double sum = 0.0;
        for (int i = 0; i < args.Length() - 1; ++i) {
          /* throw exception if invalid number */
          if (!args[i]->IsNumber()) {
            isolate->ThrowException(Exception::TypeError(
              String::NewFromUtf8(isolate, "Arguments Type Error.")
            ));
            return;
          } else {
            sum += args[i]->NumberValue();
          }
        }
        
        //call callback with accumulated result
        Local<Number> num = Number::New(isolate, sum);
        Local<Value> argv[1] = { num };
        callback->Call(Null(isolate), 1, argv);
      }
      
      //return obj
      void getPerson (const FunctionCallbackInfo<Value>& args) {
        Isolate* isolate = args.GetIsolate();
        
        //create object
        Local<Object> obj = Object::New(isolate);
        //set (key,val) to object
        obj->Set(
          String::NewFromUtf8(isolate, "firstname"),
          String::NewFromUtf8(isolate, "Java")
        );
        obj->Set(
          String::NewFromUtf8(isolate, "lastname"),
          String::NewFromUtf8(isolate, "Script")
        );
        //return object to js
        args.GetReturnValue().Set(obj);
      }
    
      //pass object to C++
      void sayHiTo (const FunctionCallbackInfo<Value>& args) {
        Isolate* isolate = args.GetIsolate();
        //get object from js
        Local<Object> person = Local<Object>::Cast(args[0]);
        //get value from object
        Local<String> fullname = String::Concat(
          person->Get(String::NewFromUtf8(isolate, "firstname"))->ToString(),
          person->Get(String::NewFromUtf8(isolate, "lastname"))->ToString()
        );
        //return value to js
        args.GetReturnValue().Set(String::Concat(
          String::NewFromUtf8(isolate, "Hi, "),fullname
        ));
      }
    
      //return function 
      void getFunction (const FunctionCallbackInfo<Value>& args) {
        Isolate* isolate = args.GetIsolate();
        //create js function
        Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, sayHiTo);
        Local<Function> fn = tpl->GetFunction();
        fn->SetName(String::NewFromUtf8(isolate, "sayHiTo"));
        //return function to js
        args.GetReturnValue().Set(fn);
      }
    
    
      //initializtion function which is called when module is loaded into NodeJS for first time
      void init (Local<Object> exports) {
        /* exports method hello */
        /* same as javascript's module.exports.hello = hello */
        /* NODE_SET_METHOD can have many */
        
        NODE_SET_METHOD(exports, "hello", hello);
        NODE_SET_METHOD(exports, "accumulate", accumulate);
        NODE_SET_METHOD(exports, "getPerson", getPerson);
        NODE_SET_METHOD(exports, "getFunction", getFunction);
      }
    
      //macro, set initializtion method of module
      NODE_MODULE(NODE_GYP_MODULE_NAME, init)
    }

    //build addon
    file: binding.gyp
    {
       "targets": [

         {
           "target_name": "myaddon",
           "sources": ["hello.cc"]
        },{
          "target_name": "accumulate",
          "sources": ["accumulate.cc"]
       }]
    }


    command:
    node-gyp configure
    node-gyp build

    Using:

    const myaddon = require('./build/Release/myaddon')
    
    console.log('[HelloWorldDemo]' + myaddon.hello())
    
    myaddon.accumulate(1, 3, 4, 7, (sum) => {
      console.log('[FunctionArgumentsAndCallbacksDemo] 1 + 3 + 4 + 7 = ' + sum)
    })
    
    try {
      myaddon.accumulate(1, 2, 'a', (sum) => {
        console.log(sum)
      })
    } catch (err) {
      console.log('[ExceptionDemo] ' + err)
    }
    
    let someone = myaddon.getPerson()
    console.log('[ReturnObjectDemo] ' + someone.firstname + someone.lastname)
    
    // return-function demo
    let sayHiTo = myaddon.getFunction()
    console.log('[ReturnFunctionDemo] ' + sayHiTo(someone))
  • 相关阅读:
    案例详解:MTU不一致导致主机和RAC不断重启
    近千人观看live,晚8点继续安排,2个CPU过高案例+1个文件数据删除案例->Oracle故障分析的方法论+DBA能力提升要领...
    一个模版让报表自动生成,领导:这才是数据分析人该干的事
    如何构造一个 SYN_SENT 状态的连接
    TCP 3次握手原理
    SpringCloud Alibaba微服务番外一
    socket bind 随机端口
    Yii项目Security加密解密类提取
    linux中iptables配置文件及命令详解详解
    linux中iptables配置文件及命令详解详解
  • 原文地址:https://www.cnblogs.com/iiiDragon/p/11658450.html
Copyright © 2020-2023  润新知