In short, the main content of this article is to use CC ++ to implement Node. js modules are very good. If you need them, you can refer to a pitfall N long ago-use Node. js to refactor NBUT's Online Judge, including the evaluation end. (Don't worry about when it's done. (/‵ Д ′)/~ Zookeeper
In short, what we need to do now is simply to use C/C ++ to implement the Node. js module.
Preparations
To do well, you must first ~~ Rogue games ~~ Utility.
Node-gyp
First, you need a node-gyp module.
In any corner, execute:
The Code is as follows:
$ Npm install node-gyp-g
After a series of blahblah operations, you have installed it.
Python
Then you need a python environment.
Go to the official website.
Note: According to node-gyp GitHub, make sure that your python version is between 2.5.0 and 3.0.0.
Compiling environment
Well, I'm just a little lazy. Please also go to node-gyp to see the compiler requirements. And it's easy.
Getting started
Let me get started with Hello World on the official website.
Hello World
Prepare a C ++ file, for example ~~ Sb. cc ~~ Hello. cc.
Next, let's work out the header file and define the namespace step by step:
The Code is as follows:
# Include
# Include
Using namespace v8;
Main functions
Next, we will write a function whose return value is Handle. .
The Code is as follows:
Handle Hello (const Arguments & args)
{
//... Waiting for writing
}
Then I will explain these things in a rough way:
Handle
To be honest, I declare in advance that I have referenced it from here (@ fool.
In V8, the Handle type is used to host JavaScript objects. Similar to C ++'s std: sharedpointer, the value assignment between Handle types directly transmits object references. However, v8 uses its own GC to manage the object lifecycle, rather than the reference count commonly used by smart pointers.
JavaScript types have their own custom types in C ++, such as String, Integer, Object, Date, and Array. They strictly abide by the inheritance relationships in JavaScript. When using these types in C ++, Handle must be used for management of their lifecycles using GC instead of native stacks and stacks.
The so-called Value can be seen from the various inheritance relationships in the header file v8.h of the V8 engine. It is actually the base class of various objects in JavaScript.
After learning about this, we can basically understand the meaning of the above function statement, that is, we write a Hello function, which returns an indefinite value.
Note: we can only return specific types, such as String, Integer, and so on under Handle.
Arguments
This is the parameter passed in to this function. We all know that in Node. js, the number of parameters is messy. When these parameters are passed in to C ++, they become the Arguments type objects.
The specific usage will be discussed later. Here we only need to understand what this is. (For Mao to sell? Because the examples in the official Node. js documents are separated, I am only talking about the first Hello World example ('Too many then) σ
Adding bricks and tiles
Next, we will begin to contribute. The simplest sentence is:
The Code is as follows:
Handle Hello (const Arguments & args)
{
HandleScope scope;
Return scope. Close (String: New ("world "));
}
What do these two sentences mean? The general meaning is to return a Node. js string "world ".
HandleScope
For more information, see here.
The lifecycle of Handle is different from that of the C ++ smart pointer. Instead of living in the scope of C ++ semantics (that is, the part surrounded by {}), HandleScope must be specified manually. HandleScope can only be allocated to the stack. After the HandleScope object is declared, the Handle created after it is managed by HandleScope. After the HandleScope object is parsed, the Handle managed by it will be determined by GC whether to recycle.
So, we have to declare this Scope when we need to manage its lifecycle. Okay. Why isn't our code written like this?
The Code is as follows:
Handle Hello (const Arguments & args)
{
HandleScope scope;
Return String: New ("world ");
}
Because when the function returns, the scope will be destructed, And the Handle managed by it will be recycled, so this String will become meaningless.
So V8 came up with a magical idea -- HandleScope: Close (Handle Value) function! The purpose of this function is to close the Scope and forward the parameters to the previous Scope for management, that is, to enter the Scope before the function.
So we have the previous Code scope. Close (String: New ("world "));.
String: New
This String class corresponds to the original String class of Node. js. It inherits from the Value class. Similarly, there are:
• Array
• Integer
• Boolean
• Object
• Date
• Number
• Function
•...
Some of these are inherited from values, and some are secondary inheritance. We will not do more research here. We can look at V8 code (at least header files) for research or look at this manual.
What about New? Here you can see. Is to create a String object.
So far, the main function is parsed.
Export object
Let's take a look. If it is written in Node. js, how can we export functions or objects?
The Code is as follows:
Exports. hello = function (){}
So how can we achieve this step in C ++?
Initialization Function
First, we write an initialization function:
The Code is as follows:
Void init (HandleExports)
{
//... Waiting for your sister! # Too many rows) Too many ☆) too many rows) Too many rows
}
This is a turtle! The function name does not matter, but the input parameter must be a Handle., Which means that we will export the items on the goods below.
Then, we will write the exported items here:
The Code is as follows:
Void init (HandleExports)
{
Exports-> Set (String: NewSymbol ("hello "),
FunctionTemplate: New (Hello)-> GetFunction ());
}
In general, adding a field named hello to this exports object is a function, and this function is our dear Hello function.
The straightforward point of writing with pseudo code is:
The Code is as follows:
Void init (HandleExports)
{
Exports. Set ("hello", function hello );
}
Success!
(It's your sister! Shut up ('taobao' quit before ☆) then ')
Export
This is the last step. We should declare that this is the export entry, so we add this line at the end of the Code:
NODE_MODULE (hello, init)
Got a Nini ?! What is this?
Don't worry. This NODE_MODULE is a macro. It means that we use the init initialization function to export the exported items to hello. So where is this hello?
It comes from the file name! Yes, that's right. It comes from the file name. You don't need to declare it in advance, and you don't have to worry about it. In short, what is the name of your finally compiled binary file name? hello here, you will fill in something. Of course, you need to remove the suffix.
For more information, see the official documentation.
Note that all Node addons must export an initialization function:
The Code is as follows:
Void Initialize (HandleExports );
NODE_MODULE (module_name, Initialize)
There is no semi-colon after NODE_MODULE as it's not a function (see node. h ).
The module_name needs to match the filename of the final binary (minus the. node suffix ).
Compiler • compiler Compiler)
Come on, let's compile it together!
Create another archive file similar to Makefile -- binding. gyp.
Add the following code:
The Code is as follows:
{
"Targets ":[
{
"Target_name": "hello ",
"Sources": ["hello. cc"]
}
]
}
Why? Refer to the official node-gyp documentation.
Configure
After the file is ready, we need to execute the command below this directory:
The Code is as follows:
$ Node-gyp configure
If everything works properly, a build directory should be generated, and related files may be the vcxproj file of M $ Visual Studio, or Makefile, depending on the platform.
Build
After Makefile is generated, we start to construct and compile:
$ Node-gyp build
It will be a real success when all compilation is complete! Check the build/Release directory. Is there a hello. node file below? That's right. This is the soap to be picked up for Node. js in C ++!
Get it done! Node worker (compute worker) implements C ++
Create a new file named jianfeizao. js in the directory just now:
The Code is as follows:
Var addon = require ("./build/Release/hello ");
Console. log (addon. hello ());
No! No! Come out! The result of Node. js and C ++! This addon. hello () is the Handle we wrote in C ++ code. Hello (const Arguments & args). Now we have output the returned value.
Wash and sleep, more in-depth next section
It's not too early. Today we will write it here. So far, everyone can develop the most basic Hello world C ++ extension. The next write should be more in-depth. I don't know the next time.
(Hey, hey, how can the supervisor be so irresponsible! (O ゚ ロ ゚) ┌ ┛ Σ (ノ 'ω ') then