1.环境
Ubuntu 14.04
node 4.5.0
node-gyp 3.4.0
2.项目
新建项目,加入组件nan和bindings
方法一、在项目文件的node_modules中复制组件nan和bindings的全部代码包;
方法二、在package.json的dependencies中加入这两个组件,用nmp安装
3.c++源码
//pi_est.h
#ifndef PI_EST_H
#define PI_EST_H
double Estimate(int points);
#endif
//pi_est.cc
#include <cstdlib>
#include "pi_est.h"
inline int randall(unsigned int *p_seed) {
#ifdef _WIN32
return rand();
#else
return rand_r(p_seed);
#endif
}
double Estimate(int points){
int i = points;
int inside = 0;
unsigned int randseed = 1;
#ifdef _WIN32
srand(randseed);
#endif
unsigned int seed = randall(&randseed);
#ifdef _WIN32
srand(seed);
#endif
while(i-- >0) {
double x = randall(&seed)/static_cast<double>(RAND_MAX);
double y = randall(&seed)/static_cast<double>(RAND_MAX);
if((x*x)+(y*y) <= 1){
inside++;
}
}
return (inside/ static_cast<double>(points))*4;
}
//sync.h
#ifndef SYNC_H
#define SYNC_H
#include <nan.h>
NAN_METHOD(CalculateSync);
#endif
//sync.cc
#include <nan.h>
#include "pi_est.h"
#include "sync.h"
NAN_METHOD(CalculateSync) {
int points = info[0]->Uint32Value();
double est = Estimate(points);
info.GetReturnValue().Set(est);
}
//async.h
#ifndef ASYNC_H
#define ASYNC_H
#include <nan.h>
NAN_METHOD(CalculateAsync);
#endif
//async.cc
#include <nan.h>
#include "pi_est.h" // NOLINT(build/include)
#include "async.h" // NOLINT(build/include)
using v8::Function;
using v8::Local;
using v8::Number;
using v8::Value;
using Nan::AsyncQueueWorker;
using Nan::AsyncWorker;
using Nan::Callback;
using Nan::HandleScope;
using Nan::New;
using Nan::Null;
using Nan::To;
class PiWorker : public AsyncWorker {
public:
PiWorker(Callback *callback, int points)
: AsyncWorker(callback), points(points), estimate(0) {}
~PiWorker() {}
// Executed inside the worker-thread.
// It is not safe to access V8, or V8 data structures
// here, so everything we need for input and output
// should go on `this`.
void Execute () {
estimate = Estimate(points);
}
// Executed when the async work is complete
// this function will be run inside the main event loop
// so it is safe to use V8 again
void HandleOKCallback () {
HandleScope scope;
Local<Value> argv[] = {
Null()
, New<Number>(estimate)
};
callback->Call(2, argv);
}
private:
int points;
double estimate;
};
// Asynchronous access to the `Estimate()` function
NAN_METHOD(CalculateAsync) {
int points = To<int>(info[0]).FromJust();
Callback *callback = new Callback(info[1].As<Function>());
AsyncQueueWorker(new PiWorker(callback, points));
}
//addon.cc
#include <nan.h>
#include "sync.h" // NOLINT(build/include)
#include "async.h" // NOLINT(build/include)
using v8::FunctionTemplate;
using v8::Handle;
using v8::Object;
using v8::String;
using Nan::GetFunction;
using Nan::New;
using Nan::Set;
// Expose synchronous and asynchronous access to our
// Estimate() function
NAN_MODULE_INIT(InitAll) {
Set(target, New<String>("calculateSync").ToLocalChecked(),
GetFunction(New<FunctionTemplate>(CalculateSync)).ToLocalChecked());
Set(target, New<String>("calculateAsync").ToLocalChecked(),
GetFunction(New<FunctionTemplate>(CalculateAsync)).ToLocalChecked());
}
NODE_MODULE(addon, InitAll)
4.binding.gyp
{
"targets": [
{
"target_name": "addon",
"sources": [
"addon.cc",
"pi_est.cc",
"sync.cc",
"async.cc"
],
"include_dirs": ["<!(node -e \"require('nan')\")"]
}
]
}
5.js源码
//addon.js
var addon = require('bindings')('addon');
var calculations = process.argv[2] || 100000000;
function printResult(type, pi, ms) {
console.log(type, 'method:');
console.log('\tπ ≈ ' + pi +
' (' + Math.abs(pi - Math.PI) + ' away from actual)');
console.log('\tTook ' + ms + 'ms');
console.log();
}
function runSync() {
var start = Date.now();
// Estimate() will execute in the current thread,
// the next line won't return until it is finished
var result = addon.calculateSync(calculations);
printResult('Sync', result, Date.now() - start);
console.log("sync====after result======");
}
function runAsync() {
// how many batches should we split the work in to?
var batches = process.argv[3] || 16;
var ended = 0;
var total = 0;
var start = Date.now();
function done (err, result) {
total += result;
// have all the batches finished executing?
if (++ended === batches) {
printResult('Async', total / batches, Date.now() - start);
}
}
// for each batch of work, request an async Estimate() for
// a portion of the total number of calculations
for (var i = 0; i < batches; i++) {
addon.calculateAsync(calculations / batches, done);
}
console.log("async====before result=========");
}
runSync();
runAsync();
6.编译addon
cd到源码目录下
node-gyp configure build
7.执行
cd 到源码目录下
node addon.js