C++写node笔记(二)
by snoopyxdy
at 2012-11-23 17:09:47
original http://snoopyxdy.blog.163.com/blog/static/60117440201210233473129
#include <node.h>官网有这段话:所有的node的插件必须输出一个初始化的函数,也就是说如下代码是在每个模块都必须有的,固定格式。#include <v8.h>
FunctionTemplate::New(Method)->GetFunction()); //调用类FunctionTemplate的静态成员New方法,传入Handle<Value>类型的Method,然后调用GetFunction方法生成node函数,具体v8参考手册上有说明
using namespace v8; //使用命名空间v8,不用在代码中写v8::XXXX
Handle<Value> Method(const Arguments& args) { //定义一个function,返回Handle<Value>类的值
HandleScope scope; //实例化scope,用来存放返回值
return scope.Close(String::New("world")); //将返回值丢入scope.close中
}
void init(Handle<Object> target) { //接受参数 Handle<Object>类型,注意,这里target是指针
target->Set(String::NewSymbol("hello"), //调用Set方法,对这个对象增加key和value}
NODE_MODULE(hello, init) //固定将文件名hello,和init初始化函数丢入NODE_MODULE
void Initialize (Handle<Object> target);
NODE_MODULE(module_name, Initialize)
代码例子很简单,我们主要看到了几个新东西:#define BUILDING_NODE_EXTENSION
#include <node.h>
using namespace v8;
Handle<Value> Add(const Arguments& args) {
HandleScope scope;
if (args.Length() < 2) { //如果args的长度小于2,则抛出错误,从下面代码我们知道如何抛出一个错误,以后照搬就行
ThrowException(Exception::TypeError(String::New("Wrong number of arguments")));
return scope.Close(Undefined());//返回Udefined
}
if (!args[0]->IsNumber() || !args[1]->IsNumber()) {//判断2个参数是否是number
ThrowException(Exception::TypeError(String::New("Wrong arguments")));
return scope.Close(Undefined());
}
Local<Number> num = Number::New(args[0]->NumberValue() + args[1]->NumberValue());//将参数转化成C++可用的double型相加,然后再转化成输出给node的Number型,最后赋值给 Local<Number> 类型的变量 num,返回给用户
return scope.Close(num);
}
void Init(Handle<Object> target) {
target->Set(String::NewSymbol("add"),
FunctionTemplate::New(Add)->GetFunction());
}
NODE_MODULE(addon, Init)
String::New("Wrong arguments")
这表示将js传递过来的Number型变为C++可用的double型args[0]->NumberValue()
var addon = require('./build/Release/addon');
console.log( 'This should be eight:', addon.add(3,5) );
js端调用代码:#define BUILDING_NODE_EXTENSION
#include <node.h>
using namespace v8;
Handle<Value> RunCallback(const Arguments& args) {
HandleScope scope;
Local<Function> cb = Local<Function>::Cast(args[0]); //将参数第一个也就是js传递过来的回调函数转化成c++的function
const unsigned argc = 1; //定义无符号int argc为1
Local<Value> argv[argc] = { Local<Value>::New(String::New("hello world")) };//创建一个数组,长度为1,
cb->Call(Context::GetCurrent()->Global(), argc, argv);//利用local<function>的call方法然后将上下文,参数长度,以及参数数组传入call方法,即调用js端的回调
return scope.Close(Undefined()); //返回undeined,无返回值
}
void Init(Handle<Object> target) {
target->Set(String::NewSymbol("runCallback"),
FunctionTemplate::New(RunCallback)->GetFunction());
}
NODE_MODULE(addon, Init)
var addon = require('./build/Release/addon');
addon.runCallback(function(msg){
console.log(msg); // 'hello world'
});
我们向一个数组push对象1千万个,输出时间为:console.time('for');
var ary = [];
for(var i=0;i<10000000;i++){
ary.push({"aaa":123})
}
console.timeEnd('for');
我们编写一个同样功能的c++代码:for: 3972ms
node端的代码:#define BUILDING_NODE_EXTENSION
#include <node.h>
using namespace v8;
Handle<Value> CreateObject(const Arguments& args) {
HandleScope scope;
Handle<Value> k = args[0]->ToString(); //将传递的第一个参数转化为String类型
Local<Object> obj = Object::New();//创建一个js的空对象
if(args[1]->IsBoolean()){ //如果第二个参数是布尔值,则转化为布尔型
obj->Set(k, args[1]->ToBoolean());
}
else if(args[1]->IsNumber()){ //如果第二个参数是数值,则转化为整形
obj->Set(k, args[1]->ToNumber());
}
else obj->Set(k, args[1]->ToString()); //否则转化为字符串
int n = args[2]->NumberValue(); //将第三个参数转化为double
Handle<Array> ary = Array::New(n); //构建js数组,长度为n
for(int i=0;i<n;i++){
ary->Set(Integer::New(i), obj); //循环的往js数组内插入obj对象
}
return scope.Close(ary); //将数组输出给node端
}
void Init(Handle<Object> target) {
target->Set(String::NewSymbol("createObject"),
FunctionTemplate::New(CreateObject)->GetFunction());
}
NODE_MODULE(object, Init)
console.time('for');
var cr= require('./addon/build/Release/object.node').createObject;
var ary = cr("aaa",123,10000000);
console.timeEnd('for');
执行时间:
for: 2114ms