Three implementation methods for writing components in Node. js _ node. js

Source: Internet
Author: User
This article mainly introduces Node. three implementation methods of js writing components, including pure js implementation, v8API implementation (synchronous & amp; asynchronous), and implementation using the swig framework, if you are interested, refer to the following: first, we will introduce the differences between using v8 APIs and using swig frameworks:

(1) v8 API is an official native method with powerful and complete functions. The disadvantage is that you need to be familiar with v8 API, which is difficult to compile and is highly relevant to js, it is not easy to support other scripting languages.

(2) swig is a third-party support, a powerful component development tool that supports generating C ++ component packaging code for multiple common scripting languages such as python, lua, and js, swig users only need to write C ++ code and swig configuration files to develop C ++ components in various scripting languages. They do not need to understand the component development framework of various scripting languages, the disadvantage is that javascript callback is not supported. The documentation and demo code are not complete and there are not many users.

1. Implement Node. JS components using pure js
(1) Run npm init in the helloworld directory to initialize package. json. The options are ignored by default.

(2) component implementation index. js, for example:

module.exports.Hello = function(name) {    console.log('Hello ' + name);}

(3) Run npm install./helloworld and helloworld in the outer directory to install it in the node_modules directory.
(4) Compile the component code:

Var m = require ('helloworld'); m. Hello ('zhangsan'); // output: Hello zhangsan

Ii. Use v8 API to implement JS components-synchronous Mode
(1) Write binding. gyp, eg:

{ "targets": [  {   "target_name": "hello",   "sources": [ "hello.cpp" ]  } ]}

(2) Compile the component implementation hello. cpp, eg:

# Include
 
  
Namespace cpphello {using v8: FunctionCallbackInfo; using v8: Isolate; using v8: Local; using v8: Object; using v8: String; using v8: Value; void Foo (const FunctionCallbackInfo
  
   
& Args) {Isolate * isolate = args. getIsolate (); args. getReturnValue (). set (String: NewFromUtf8 (isolate, "Hello World");} void Init (Local
   Exports) {NODE_SET_METHOD (exports, "foo", Foo);} NODE_MODULE (cpphello, Init )}

(3) Compile Components

The hello. node module is generated in the node-gyp worker Enode-gyp build./build/Release/directory.

(4) Compile and test js Code

Const m = require ('./build/Release/hello') console. log (m. foo (); // output hello World

(5) add package. json to install eg:

{                                                                                                           "name": "hello",  "version": "1.0.0",  "description": "",   "main": "index.js?6.1.3",  "scripts": {    "test": "node test.js?6.1.3"  },   "author": "",   "license": "ISC"}

(5) install the component to node_modules

Go to the parent directory of the component directory and run npm install./helloc // Note: helloc is the component directory.
The hello module is installed in the node_modules directory in the current directory. The test code is written as follows:

var m = require('hello');console.log(m.foo());  

Iii. Use v8 API to implement JS components-asynchronous mode
The above describes the synchronization component. foo () is a synchronous function, that is, the caller of the foo () function must wait until the foo () function is executed before it can go down. When foo () when a function is a function with IO time-consuming operations, asynchronous foo () functions can reduce blocking waits and improve overall performance.

To Implement Asynchronous components, you only need to pay attention to the uv_queue_work API of libuv. In addition to the main code hello. cpp and the Component User code, the other parts are consistent with the demo above.

Hello. cpp:

/** Node. js cpp Addons demo: async call and call back. * gcc 4.8.2 * author: cswuyg * Date: 2016.02.22 **/# include
     
      
# Include
      
       
# Include
       
        
# Include
        
         
# Include
         
          
# Include
          
            Namespace cpphello {using v8: FunctionCallbackInfo; using v8: Function; using v8: Isolate; using v8: Local; using v8: Object; using v8: Value; using v8: Exception; using v8: Persistent; using v8: HandleScope; using v8: Integer; using v8: String; // async task struct MyTask {uv_work_t work; int a {0}; int B {0}; int output {0}; unsigned long work_tid {0}; unsigned long main_tid {0}; Persistent
           
             Callback;}; // async function void query_async (uv_work_t * work) {MyTask * task = (MyTask *) work-> data; task-> output = task-> a + task-> B; task-> work_tid = pthread_self (); usleep (1000*1000*1 ); // 1 second} // async complete callback void query_finish (uv_work_t * work, int status) {Isolate * isolate = Isolate: GetCurrent (); HandleScope handle_scope (isolate ); myTask * task = (MyTask *) work-> data; const unsigned int argc = 3; std: stringstream stream; stream <task-> main_tid; std :: string main_tid_s {stream. str ()}; stream. str (""); stream <task-> work_tid; std: string work_tid_s {stream. str ()}; Local
            
              Argv [argc] = {Integer: New (isolate, task-> output), String: NewFromUtf8 (isolate, main_tid_s.c_str (), String: NewFromUtf8 (isolate, work_tid_s.c_str ()}; Local
             
               : New (isolate, task-> callback)-> Call (isolate-> GetCurrentContext ()-> Global (), argc, argv); task-> callback. reset (); delete task;} // async main void async_foo (const FunctionCallbackInfo
              
                & Args) {Isolate * isolate = args. GetIsolate (); HandleScope handle_scope (isolate); if (args. Length ()! = 3) {isolate-> ThrowException (Exception: TypeError (String: NewFromUtf8 (isolate, "arguments num: 3"); return;} if (! Args [0]-> IsNumber () |! Args [1]-> IsNumber () |! Args [2]-> IsFunction () {isolate-> ThrowException (Exception: TypeError (String: NewFromUtf8 (isolate, "arguments error"); return ;} myTask * my_task = new MyTask; my_task-> a = args [0]-> ToInteger ()-> Value (); my_task-> B = args [1]-> ToInteger ()-> Value (); my_task-> callback. reset (isolate, Local
               
                 : Cast (args [2]); my_task-> work. data = my_task; my_task-> main_tid = pthread_self (); uv_loop_t * loop = uv_default_loop (); uv_queue_work (loop, & my_task-> work, query_async, query_finish );} void Init (Local
                Exports) {NODE_SET_METHOD (exports, "foo", async_foo);} NODE_MODULE (cpphello, Init )}

The idea of Asynchronization is simple. You can call uv_queue_work to implement a working function, a completed function, and a struct that carries data transmitted across threads. The difficulty is to be familiar with v8 data structures and APIs.

Test. js

// test helloUV module'use strict';const m = require('helloUV')m.foo(1, 2, (a, b, c)=>{  console.log('finish job:' + a);  console.log('main thread:' + b);  console.log('work thread:' + c);});/*output:finish job:3main thread:139660941432640work thread:139660876334848*/

Iv. Implement Node. js components using swig-javascript
Use the swig framework to compile Node. js Components

(1) Compile the component implementation: *. h and *. cpp

Eg:

namespace a {  class A{  public:    int add(int a, int y);  };  int add(int x, int y);}

(2) Compile *. I to generate the swig packaged cpp File
Eg:

/* File : IExport.i */%module my_mod %include "typemaps.i"%include "std_string.i"%include "std_vector.i"%{#include "export.h"%} %apply int *OUTPUT { int *result, int* xx};%apply std::string *OUTPUT { std::string* result, std::string* yy };%apply std::string &OUTPUT { std::string& result };                                                                                 %include "export.h"namespace std {  %template(vectori) vector
                  
                   ;  %template(vectorstr) vector
                   
                    ;};
                   
                  

The preceding % apply indicates int * result, int * xx, std: string * result, std: string * yy, std: string & result indicates the output description, this is a typemap and a replacement.
In C ++ function parameters, if the pointer parameter is returned (through *. (OUTPUT in the I file), swig will process them as the return values of JS functions. If there are multiple pointers, the return value of JS functions is list.
% Template (vectori) vector It indicates that a vectori type is defined for JS, which is generally used by the C ++ Function As a parameter or return value, you need to use it when writing JavaScript code.
(3) Write binding. gyp for node-gyp compilation.
(4) Pay attention to the v8 version information when generating the warpper cpp file. For example: swig-javascript-node-c ++-DV8_VERSION = 0x040599 example. I
(5) Compile and Test
The difficulty lies in the use of stl and custom types. There are too few official documents in this regard.
For how to encapsulate std: vector and std: string, swig-javascript, see my exercises. Focus on the Implementation of *. I files.
V. Others
When using v8 API to implement Node. js components, we can find similarities with implementing Lua components. Lua has a state machine and Node has Isolate.

When Node exports an object, it needs to implement a constructor, add a "member function" to it, and finally export the constructor as a class name. When using Lua to export objects, you also need to implement a factory function for creating objects. You also need to add "member functions" to the table. Finally, export the factory function.

Node js scripts have new keywords and Lua does not. Therefore, Lua only provides the object factory for creating objects, while Node can provide the object factory or class encapsulation.

The above is all the content of this article, hoping to help you learn.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.