我正在尝试更好地理解开发使用 C++ 包装器的 Nodejs 模块所需的技术。我正在研究尽可能多的信息,例如Nodejs Documentation。为了加深我的理解,我设置了编写 Nodejs 模块的挑战,该模块可以以类似的方式使用:
var addon = require('./fruit.js');
var apple = new addon.Fruit(5,7);
var pear = new addon.Fruit(3,6);
console.log("Apple: weight = " + apple.getWeight() + " calories = "
+ apple.getCalories());
var bunch = new addon.Grapes( 50, 2, 2 );
console.log("Calories of a grape: " + bunch.getCalories());
console.log("Total weight of grapes: " + bunch.getBunchWeight());
Fruit.js在哪里:
function Fruit(weight, calories) {
this.weight = weight;
this.calories = calories;
}
Fruit.prototype.getWeight = function() {
return this.weight;
};
Fruit.prototype.getCalories = function() {
return this.calories;
};
Grapes.prototype = new Fruit();
Grapes.prototype.constructor=Grapes;
function Grapes(number, weight, calories) {
this.number=number;
this.weight=weight;
this.calories=calories;
}
Grapes.prototype.getTotalWeight = function () {
return this.number * this.weight;
}
exports.Fruit = Fruit;
exports.Grapes = Grapes;
为了使用 C++ 包装器开发 Nodejs 模块,我完成了Stack Overflow发布,但是当我将参数添加到继承的类时,参数没有传递给基类。我尝试了许多解决方案,但我觉得我对Inherit(Handle parent)函数的理解是我出错的地方。代码如下:
mymod_wrap.h
#ifndef MYOBJECT_WRAP_H
#define MYOBJECT_WRAP_H
#include <node.h>
using namespace v8;
class Fruit : public node::ObjectWrap {
public:
Fruit();
~Fruit();
static Persistent<FunctionTemplate> fruit_template;
static void Init(Handle<Object> exports);
static Handle<Value> New(const Arguments& args);
static Handle<Value> GetWeight(const Arguments& args);
static Handle<Value> GetCalories(const Arguments& args);
private:
double weight_;
double calories_;
};
class Grapes : public node::ObjectWrap {
public:
Grapes();
~Grapes();
static Persistent<FunctionTemplate> grapes_template;
static void Init(Handle<Object> exports);
static Handle<Value> New(const Arguments& args);
static Handle<Value> GetBunchWeight(const Arguments& args);
private:
int number_;
};
#endif
mymod_wrap.cc
#include <node.h>
#include "mymod_wrap.h"
using namespace v8;
Fruit::Fruit() {};
Fruit::~Fruit() {};
void Fruit::Init(Handle<Object> exports) {
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
fruit_template = Persistent<FunctionTemplate>::New(tpl);
fruit_template->InstanceTemplate()->SetInternalFieldCount(1);
fruit_template->SetClassName(String::NewSymbol("Fruit"));
NODE_SET_PROTOTYPE_METHOD(fruit_template, "getWeight", GetWeight);
NODE_SET_PROTOTYPE_METHOD(fruit_template, "getCalories", GetCalories);
exports->Set(String::NewSymbol("Fruit"), fruit_template->GetFunction());
}
Handle<Value> Fruit::New(const Arguments& args) {
HandleScope scope;
Fruit* obj = new Fruit(); // Conventional C++ Call see notes
obj->weight_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
obj->calories_ = args[1]->IsUndefined() ? 0 : args[1]->NumberValue();
obj->Wrap(args.This());
return args.This();
}
Handle<Value> Fruit::GetWeight(const Arguments& args) {
HandleScope scope;
Fruit* obj = ObjectWrap::Unwrap<Fruit>(args.This());
return scope.Close(Number::New(obj->weight_));
}
Handle<Value> Fruit::GetCalories(const Arguments& args) {
HandleScope scope;
Fruit* obj = ObjectWrap::Unwrap<Fruit>(args.This());
return scope.Close(Number::New(obj->calories_));
}
Persistent<FunctionTemplate> Fruit::fruit_template;
Grapes::Grapes() {};
Grapes::~Grapes() {};
void Grapes::Init(Handle<Object> exports) {
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
grapes_template = Persistent<FunctionTemplate>::New(tpl);
grapes_template->Inherit(Fruit::fruit_template);
grapes_template->InstanceTemplate()->SetInternalFieldCount(1);
grapes_template->SetClassName(String::NewSymbol("Grapes"));
NODE_SET_PROTOTYPE_METHOD(grapes_template, "getBunchWeight", GetBunchWeight);
exports->Set(String::NewSymbol("Grapes"), grapes_template->GetFunction());
}
Handle<Value> Grapes::New(const Arguments& args ){
HandleScope scope;
Grapes* obj = new Grapes();
obj->number_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
/* the above works but need to pass args[1], args[2] to */
/* "weight_" and "calories_" in the base class ? */
obj->Wrap(args.This());
return args.This();
}
Handle<Value> Grapes::GetBunchWeight(const Arguments& args) {
HandleScope scope;
Grapes* obj = ObjectWrap::Unwrap<Grapes>(args.This());
/* Need to unwrap the base object to get "weight_" */
/* multiply with "number_" to get the total weight of the bunch */
return scope.Close(Number::New( /* return calculated total weight */));
}
Persistent<FunctionTemplate>Grapes::grapes_template;
我的mod.cc
#include <node.h>
#include "mymod_wrap.h"
using namespace v8;
void InitAll(Handle<Object> exports) {
Fruit::Init(exports);
Grapes::Init(exports);
}
NODE_MODULE(fruit, InitAll)
我在代码中添加了一些注释来表明我认为问题出在哪里。
感谢任何关于我哪里出错的指示。