• 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))
  • 相关阅读:
    CSP-S全国模拟赛第三场 【nan死了】
    ●SCOI2018 AFO
    ●洛谷P2934 [USACO09JAN]安全出行Safe Travel
    ●洛谷P3233 [HNOI2014]世界树
    ●洛谷P2495 [SDOI2011]消耗战
    ●UOJ58 [WC2013]糖果公园
    ●洛谷P1903 [国家集训队]数颜色
    ●BZOJ 4237 稻草人
    ●Joyoi Normal
    ●CodeForces 698C LRU
  • 原文地址:https://www.cnblogs.com/iiiDragon/p/11658450.html
Copyright © 2020-2023  润新知