Correct Method for writing Node. js plug-ins _ node. js

Source: Internet
Author: User
Tags install node
As Node. js said in its official documentation, the plug-in is a shared object that dynamically links JavaScript code to the CC ++ library. This means that we can reference any content from the CC ++ library and include it into Node. js by creating a plug-in. Node. js uses JavaScript to write backend results, which deserves more efforts. However, if you need some functions that cannot be used directly or even modules that cannot be implemented at all, can you introduce such results from the C/C ++ library? The answer is yes. All you need to do is compile a plug-in and use the resources of other code libraries in your JavaScript code. Next we will start our inquiry tour together.

Introduction

As Node. js said in its official documentation, the plug-in is a shared object that dynamically links JavaScript code to the C/C ++ library. This means that we can reference any content from the C/C ++ library and include it in Node. js by creating a plug-in.

As an instance, we will create a set of encapsulation for the standard std: string object.

Preparations

Before writing, make sure that you have prepared all the materials required for subsequent module compilation. You need node-gyp and all its dependencies. You can use the following command to install node-gyp:

npm install -g node-gyp

In terms of dependencies, we need to prepare the following projects for Unix systems: • Python (version 2.7 is required, and 3.x cannot work properly)

• Make

• A c ++ compiler tool chain (such as gpp or g ++)

For example, on Ubuntu, you can use the following command to install all the above projects (Python 2.7 should have been installed in advance ):

sudo apt-get install build-essentials 

In Windows, what you need is:

• Python (2.7.3, 3.x cannot work properly)

• Microsoft Visual Studio C ++ 2010 (applicable to Windows XP/Vista)

• Microsoft Visual Studio C ++ 2012 for Windows Desktop (for Windows 7/8)

Note that the Express version of Visual Studio can work normally.

Binding. gyp File

This file is used by node-gyp to generate an appropriate build file for our plug-in. You can click here to view the. gyp documentation provided by Wikipedia. However, the instance we want to use today is very simple, so you only need to use the following code:

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

Target_name can be set to anything you like. The sources array contains all the source files required by the plug-in. Our instance also includes addon. cc, which is used to accommodate the Code required for compiling plug-ins and stdstring. cc, and our encapsulation class.

STDStringWrapper class

The first step is to define our own class in the stdstring. h file. If you are familiar with C ++ programming, you will not be unfamiliar with the following two lines of code.

#ifndef STDSTRING_H #define STDSTRING_H

This is a standard include guard. Next, we need to include the following two headers in the include category:

# Include
# Include
The first is oriented to the std: string class, while the second include applies to all content related to Node and V8.

After completing this step, we can declare our own classes:

Class STDStringWrapper: public node: ObjectWrap {
For all the classes we intend to include in the plug-in, we must extend the node: ObjectWrap class.

Now we can start to define the private attribute of this class:

private:   std::string* s_;     explicit STDStringWrapper(std::string s = "");   ~STDStringWrapper();

In addition to constructors and resolution functions, we also need to define a pointer for std: string. This is the core of the technology and can be used to connect the C/C ++ code library to the Node. We define a private pointer for the C/C ++ class, the pointer will be used in all subsequent methods to implement the operation.

Now we declare the constructor static attribute, which provides functions for the class we created in V8:

Static v8: Persistent constructor;
If you are interested, click here to refer to the template description solution for more details.

Now we need a New method, which will be assigned to the constructor mentioned above, and V8 will initialize our class:

Static v8: Handle New (const v8: Arguments & args );
Every function Acting on V8 should follow the following requirements: it will accept a reference pointing to the v8: Arguments object and return a v8: Handle> v8 :: value> -- this is the consistent way That V8 handles weak JavaScript when using strong-type C ++ encoding.

After that, we need to insert the other two methods into the prototype of the object:

static v8::Handle add(const v8::Arguments& args); static v8::Handle toString(const v8::Arguments& args);

The toString () method allows us to obtain the value of s _ when used together with a common JavaScript string, rather than the value of [Object object.

Finally, we will introduce the initialization method (this method will be called by V8 and assigned to the constructor function) and disable include guard:

public:     static void Init(v8::Handle exports); };   #endif

The exports object is equivalent to module. exports in the JavaScript module.

Stdstring. cc file, constructor, and parsing function

Create the stdstring. cc file. First, we need to include our header:

#include "stdstring.h" 

The following defines attributes for constructor (because it belongs to a static function ):

v8::Persistent STDStringWrapper::constructor; 

This class service constructor will assign the s _ attribute:

STDStringWrapper::STDStringWrapper(std::string s) {   s_ = new std::string(s); }

The parsing function will delete it to avoid memory overflow:

STDStringWrapper::~STDStringWrapper() {   delete s_; }

In addition, you must delete all the content allocated with new, because every such situation may cause exceptions. Therefore, please remember the above operations or use shared pointers.

Init Method

This method will be called by V8 to initialize our class (assign a constructor to place all the content we intend to use in JavaScript in the exports object ):

Void STDStringWrapper: Init (v8: Handle exports ){
First, we need to create a function template for our New method:

V8: Local tpl = v8: FunctionTemplate: New (New );
This is a bit similar to the new Function in JavaScipt -- it allows us to prepare our own JavaScript class.

Now we can set the name for the function as needed (if you miss this step, the constructor will be in the anonymous state, that is, the name is function someName () {} or function (){}):

Tpl-> SetClassName (v8: String: NewSymbol ("STDString "));
We use v8: String: NewSymbol () to create a special type String for the attribute name-which saves a little time for the engine to operate.

After that, we need to set the number of fields in our class instance:

Tpl-> InstanceTemplate ()-> SetInternalFieldCount (2 );
We have two methods -- add () and toString (), so we set the number to 2. Now we can add our methods to the function prototype:

Tpl-> PrototypeTemplate ()-> Set (v8: String: NewSymbol ("add"), v8: FunctionTemplate: New (add)-> GetFunction ());
Tpl-> PrototypeTemplate ()-> Set (v8: String: NewSymbol ("toString"), v8: FunctionTemplate: New (toString)-> GetFunction ());
This part of the code seems to be large, but you only need to carefully observe the rules: We use tpl-> PrototypeTemplate ()-> Set () to add each method. We also use v8: String: NewSymbol () to provide them with names and functiontemplates.

Finally, we can place the constructor in the exports object in the constructor class attribute:

constructor = v8::Persistent::New(tpl->GetFunction());   exports->Set(v8::String::NewSymbol("STDString"), constructor); }

New Method

Now we need to define a method that works the same as JavaScript Object. prototype. constructor:

v8::Handle STDStringWrapper::New(const v8::Arguments& args) {

First, we need to create a range for it:

v8::HandleScope scope; 

After that, we can use the. IsConstructCall () method of The args object to check whether the constructor can be called using the new Keyword:

if (args.IsConstructCall()) { 

If possible, we first pass the parameter to std: string as follows:

v8::String::Utf8Value str(args[0]->ToString()); std::string s(*str);

...... In this way, we can pass it to the constructor of our encapsulated class:

STDStringWrapper* obj = new STDStringWrapper(s);

After that, we can use the. Wrap () method of the previously created object (inherited from node: ObjectWrap) to allocate it to the this variable:

obj->Wrap(args.This()); 

Finally, we can return the newly created object:

return args.This(); 

If this function cannot be called using new, we can also directly call the constructor. Next, we need to set a constant for the parameter count:

} else {   const int argc = 1; 

Now we need to use our own parameters to create an array:

v8::Local argv[argc] = { args[0] }; 

Then pass the result of constructor-> NewInstance method to scope. close, so that the object can play a role later (scope. close basically allows you to maintain the object processing handle by moving it to a higher range -- this is also the function's effective method ):

    return scope.Close(constructor->NewInstance(argc, argv));   } } 

Add Method

Now let's create the add method, which allows you to add content to the internal std: string of the object:

v8::Handle STDStringWrapper::add(const v8::Arguments& args) { 

First, we need to create a range for our function and convert this parameter to std: string as before:

v8::HandleScope scope;   v8::String::Utf8Value str(args[0]->ToString()); std::string s(*str); 

Now we need to unpack this object. We have previously performed this type of reverse encapsulation operation-this time we want to get the pointer to the object from this variable.

STDStringWrapper* obj = ObjectWrap::Unwrap(args.This()); 

Then we can access the s _ attribute and use its. append () method:

obj->s_->append(s); 

Finally, we return the current value of the s _ attribute (Use scope. Close again ):

return scope.Close(v8::String::New(obj->s_->c_str())); 

Because the v8: String: New () method can only accept char pointer as the value, we need to use obj-> s _-> c_str () to obtain it.

In this case, you should create a build directory in the plug-in folder.

Test

Now we can test our plug-in. Create a test. js file and necessary compilation library in our plug-in directory (you can skip the. node extension directly ):

var addon = require('./build/Release/addon'); 

Next, create a new instance for our object:

var test = new addon.STDString('test'); 

Perform the following operations on it, such as adding or converting it to a string:

test.add('!'); console.log('test\'s contents: %s', test); 

After running, you should see the following execution results in the console:

Conclusion

I hope that you can eliminate your concerns after reading this tutorial and consider creating and testing custom Node. js plug-ins Based on the C/C ++ library as a very difficult task. You can use this technology to easily introduce almost any C/C ++ library to Node. js. If you like, you can add more functions for the plug-in as needed. Std: string provides a large number of methods, which can be used as exercise material.

Practical links

For more information about Node. js plug-in development, V8, and C event library, see the following link.

• Node. js plug-in instructions

• V8 instructions

• Libuv (C event Library), from GitHub

Http://code.tutsplus.com/tutorials/writing-nodejs-addons--cms-21771.

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.