c++编写node的addon(10) --例子 蒙特卡罗法估算PI

本文介绍如何使用 Node.js 和 C++ 开发扩展模块,实现 π 的估算功能,并提供同步与异步两种调用方式。通过示例代码详细展示了从环境搭建、项目创建、C++ 源码编写、Node.js 接口定义到最终编译执行的全过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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   


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值