准备
nodejs和v8之间的关系
nodejs官网:
Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.
Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。
NodeJs本身核心部分就是用C++编写的,在C++中嵌入V8引擎,这样业务逻辑可以用简单的、效率很高的js去编写。 扩展nodejs本质上就是扩展v8 engine,最终让nodejs可以使用这些扩展的部分。
NodeJS可以看做是一个大的中间件,NodeJs内部也提供了很多中间件。
有了这个强大的内核,再加上渲染引擎WebKit,js能做的事情越来越多
VS Code 也是基于 Electron (原来叫 Atom Shell) 进行开发的。Electron 基于 Node.js(作为后端运行时)和 Chromium(作为前端渲染)。 www.electronjs.org/docs
开发准备
- 入门v8引擎c++开发示例 github.com/v8/v8/tree/…
- 建议使用linux环境,自带gcc
- 安装 node-gyp,和GYP(Generate Your Project)一样node依赖其他语言编写的应用时需要以平台环境现场编译。
Add-on实现
distance.cc
#include <cstdlib>
#include <cmath>
#include <nan.h>
#include <v8.h>
using Nan::AsyncQueueWorker;
using Nan::AsyncWorker;
using Nan::Callback;
using Nan::HandleScope;
using Nan::New;
using Nan::Null;
using Nan::To;
using std::pow;
using std::sqrt;
using v8::Function;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::String;
using v8::Value;
struct Point {
double x;
double y;
};
double CalculateDistance(Point* pointA, Point* pointB) {
return sqrt(pow(pointA->x - pointB->x, 2) + pow(pointA->y - pointB->y, 2));
}
class DistanceWorker : public AsyncWorker {
private:
double distance;
Point* pointA;
Point* pointB;
public:
DistanceWorker(Callback* callback, Point* pointA, Point* pointB) :
AsyncWorker(callback), pointA(pointA), pointB(pointB) {}
~DistanceWorker() {
delete pointA;
delete pointB;
}
void Execute () {
distance = CalculateDistance(pointA, pointB);
}
void HandleOKCallback () {
HandleScope scope;
Local<Value> argv[] = {
Null(),
New<Number>(distance)
};
callback->Call(2, argv);
}
};
NAN_METHOD(CalculateSync) {
Local<Object> js_pointA = To<Object>(info[0]).ToLocalChecked();
Local<Object> js_pointB = To<Object>(info[1]).ToLocalChecked();
Point* pointA = new Point();
pointA->x = To<double>(js_pointA->Get(New<String>("x").ToLocalChecked())).FromJust();
pointA->y = To<double>(js_pointA->Get(New<String>("y").ToLocalChecked())).FromJust();
Point* pointB = new Point();
pointB->x = To<double>(js_pointB->Get(New<String>("x").ToLocalChecked())).FromJust();
pointB->y = To<double>(js_pointB->Get(New<String>("y").ToLocalChecked())).FromJust();
info.GetReturnValue().Set(CalculateDistance(pointA, pointB));
}
NAN_METHOD(CalculateAsync) {
Local<Object> js_pointA = To<Object>(info[0]).ToLocalChecked();
Local<Object> js_pointB = To<Object>(info[1]).ToLocalChecked();
Callback* callback = new Callback(info[2].As<Function>());
Point* pointA = new Point();
pointA->x = To<double>(js_pointA->Get(New<String>("x").ToLocalChecked())).FromJust();
pointA->y = To<double>(js_pointA->Get(New<String>("y").ToLocalChecked())).FromJust();
Point* pointB = new Point();
pointB->x = To<double>(js_pointB->Get(New<String>("x").ToLocalChecked())).FromJust();
pointB->y = To<double>(js_pointB->Get(New<String>("y").ToLocalChecked())).FromJust();
AsyncQueueWorker(new DistanceWorker(callback, pointA, pointB));
}
NAN_MODULE_INIT(Init) {
NAN_EXPORT(target, CalculateSync);
NAN_EXPORT(target, CalculateAsync);
}
NODE_MODULE(distance, Init)
binding.gyp
{
"targets": [
{
"target_name": "distance",
"sources": [
"distance.cc"
],
"include_dirs": ["<!(node -e \"require('nan')\")"]
}
]
}
test.js
const Distance = require('./build/Release/distance');
let result;
let pointA = { x: 0, y: 0 };
let pointB = { x: 3, y: 4 };
result = Distance.CalculateSync(pointA, pointB);
if (result !== 5) throw Error(
'#Sync: Result expected to equal 5 but instead got ' + result
);
console.log('sync calculation passed');
result = Distance.CalculateAsync(pointA, pointB, (err, result) => {
if (err) throw err;
if (result !== 5) throw Error(
'#Async: Result expected to equal 5 but instead got ' + result
);
console.log('async calculation passed');
});
node-gyp rebuild # 编译C++
node test #运行效果
用java实现node扩展
Node.js想要和Java连接,需要一个 node-java 模块
放弃用Go写node扩展
起初是有这个想法...
go不能为node直接写扩展,需要c++作为中间语言通知v8调用一下go生成的扩展,这个过程就涉及到一个问题,V8类型怎样转成go类型,试了多次 gofloat64这个类型v8是没有直接对应的类型的。所以需要特殊的方法进行类型转换。不适合入门实践。
args[0]->ToNumber(isolate);
重拾用Go写node扩展
require('node-go-require'); www.npmjs.com/package/nod…
see also
Nodejs cluster模块深入探究 segmentfault.com/a/119000001…
npx: node新增工具,可以临时执行命令,减少config.js的配置