Node.js the correct way to write Plug-ins _node.js

Source: Internet
Author: User
Tags documentation function prototype prepare install node

Node.js in the use of JavaScript to write back-end effects tension pile, we should try. But if you need something that can't be used directly or even a module that can't be implemented at all, can you introduce such a result from a C + + library? The answer is yes, all you have to do is write a plugin and use the resources of other code libraries in your JavaScript code. Let's start today's enquiry together.

Introduced

As Node.js in the official documentation, Plug-ins are a shared, dynamically linked object that enables JavaScript code to be connected to A/C + + library. This means that we can refer to any content from the C + + library and incorporate it into the node.js by creating plug-ins.

As an example, we will create a package for the standard std::string object.

Preparatory work

Before we start writing, you need to make sure that you're ready for all the material you need for subsequent module compilation. Everyone needs node-gyp and all their 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 items for the UNIX system: python (2.7 version, 3.x not working properly)

make

• A C + + compiler tool chain (e.g. GPP or g++)

For example, on Ubuntu you can use the following command to install all of the above items (where Python 2.7 should have been pre-installed):

sudo apt-get install build-essentials 

In the Windows system environment, what you need is:

python (2.7.3 version, 3.x does not function properly)

• Microsoft Visual Studio C + + 2010 (for Windows Xp/vista)

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

Emphasize that Visual Studio's Express version works as well.

Binding.gyp file

This file is used by NODE-GYP to generate the appropriate build file for our plug-ins. You can click here to view the GYP documentation provided by Wikipedia, but the example we are using today is very simple, so just use the following code:

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

Where target_name can be set up for everyone to like any content. The sources array contains all the source files that the plug-in needs to use. Our example also includes addon.cc, which is designed to accommodate the code necessary to compile Plug-ins and stdstring.cc, plus our encapsulation classes.

Stdstringwrapper class

The first step we have to do is to define our own classes 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 belongs to the standard include guard. Next, we need to include the following two headers in the Include Category:

#include
#include
The first one is for the Std::string class, and the second includes all the node-and V8-related content.

Once this step is complete, we can declare our class:

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 begin to define the private properties of the class:

Private: 
  std::string* s_; 
  
  Explicit Stdstringwrapper (std::string s = ""); 
  ~stdstringwrapper ();

In addition to constructors and analytic functions, we also need to define a pointer for std::string. This is at the heart of the technology, and can be used to connect C + + code base to node--we define a private pointer for the C + + class, and we will use that pointer in all subsequent methods to implement the operation.

Now we declare the constructor static property, which will provide the function for the class we created in V8:

Static V8::P Ersistent constructor;
Interested friends can click here to see the template description scheme for more details.

Now we need a new method that will be assigned to the constructor mentioned earlier, while V8 will initialize our class:

Static V8::handle New (const v8::arguments& args);
Each function that acts on V8 should follow the following requirements: It will accept a reference to the V8::arguments object and return a v8::handle>v8::value>--this is exactly what we do when using strongly typed C + + encoding V8 the usual way of handling weakly typed JavaScript.

After that, we also need to insert two other methods into the object's prototype:

Static V8::handle Add (const v8::arguments& args); 
Static V8::handle toString (const v8::arguments& args);

The ToString () method allows us to get the value of S_ instead of the value of [object] when we use it in conjunction with a normal JavaScript string.

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

Public: 
    static void Init (V8::handle exports); 
  
#endif

Where the exports object functions in the JavaScript module is equivalent to Module.exports.

stdstring.cc files, constructors, and analytic functions

Now to create the stdstring.cc file. We first need to include our header:

#include "Stdstring.h" 

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

V8::P ersistent stdstringwrapper::constructor; 

This constructor for the class service assigns the S_ attribute:

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

And the parse function will delete it to avoid a memory overflow:

Stdstringwrapper::~stdstringwrapper () { 
  delete s_; 
}

Again, you have to delete all the content assigned with new, because each of these situations can cause an exception, so keep this in mind or use a shared pointer.

Init method

This method will be invoked by V8 to initialize our class (assigning constructor, placing all of the content we intend to use in JavaScript into exports objects):

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 somewhat similar to the new function--in Javascipt which allows us to prepare our own JavaScript classes.

Now we can set the name for the function based on the actual need (if you omit this step, the constructor will be anonymous, 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 property name-which saves a little time for the engine's operation.

After that, we need to set how many fields are included 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 own 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 looks larger, but as long as you look carefully you will find the rule: we use Tpl->prototypetemplate ()->set () to add each method. We also use V8::string::newsymbol () to provide them with names and functiontemplate.

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

constructor = V8::P ersistent::new (Tpl->getfunction ()); 
  Exports->set (V8::string::newsymbol ("stdstring"), constructor); 
}

New method

Now what we're going to do is define a method that works the same way as JavaScript Object.prototype.constructor:

V8::handle stdstringwrapper::new (const v8::arguments& args) {

We first need to create a scope for it:

V8::handlescope scope; 

After that, we can take advantage of the Args object. Isconstructcall () method to check whether the constructor can be invoked with the New keyword:

if (args. Isconstructcall ()) { 

If we can, we will first pass the parameters to the std::string as shown here:

V8::string::utf8value Str (args[0]->tostring ()); 
std::string s (*str);

...... So we can pass it to the constructor of our encapsulated class:

stdstringwrapper* obj = new Stdstringwrapper (s);

After that, we can take advantage of the object that was created earlier. Wrap () Method (inherited from Node::objectwrap) to assign it to the this variable:

Obj->wrap (args. This ()); 

Finally, we can return this newly created object:

return args. This (); 

If the function cannot be invoked with new, we can also call the constructor directly. Next, what we're going to do is 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]}; 

The result of the Constructor->newinstance method is then passed to the scope.close, so that the object can function later (Scope.close basically allows you to maintain the object by moving the handle to a higher range-- This is also how the function works):

    return scope. Close (Constructor->newinstance (argc, argv)); 
  } 
 

Add method

Now let's create the Add method, which is to allow 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 it to std::string as before:

V8::handlescope scope; 
  
V8::string::utf8value Str (args[0]->tostring ()); 
std::string s (*str); 

Now we need to split the object. We've done this reverse encapsulation before-this time we're getting pointers to objects from the this variable.

stdstringwrapper* obj = Objectwrap::unwrap (args. This ()); 

Then we can access the S_ property and use its. Append () Method:

Obj->s_->append (s); 

Finally, we return the current value of the S_ property (need to use scope again). Close):

return scope. Close (V8::string::new (Obj->s_->c_str ())); 

Because the V8::string::new () method can only accept char pointer as a value, we need to use OBJ->S_->C_STR () to get it.

You should also create a build directory in your plugin folder.

Test

Now we can test our own plug-ins. Create a test.js file in our plugin directory and the necessary compilation libraries (you can skip. Node extensions):

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

Next, create a new instance of our object:

var test = new addon. Stdstring (' Test '); 

It is then manipulated, 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 after reading this tutorial, you can reassure yourself that creating and testing a custom Node.js plug-in based on the C + + library is considered a difficult task. You can use this technology to easily bring almost any C + + library into the node.js. If you want, you can add more functionality to your plug-in based on your actual requirements. Std::string provides a number of methods that we can use as a practice material.

Useful Links

Interested friends can view the following links for more resources and details related to Node.js plug-in development, V8, and the C event loop library.

Node.js Plugin Description Document

V8 Description Document

Libuv (c event Loop Library), from GitHub

English: 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.