私は、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 モジュールを開発するために、スタック オーバーフローの投稿に取り組みましたが、継承されたクラスにパラメーターを追加すると、引数が基本クラスに渡されません。私は多くの解決策を試しましたが、 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;
mymod.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)
問題がどこにあると思われるかを示すために、コードにいくつかのコメントを追加しました。
私が間違っている場所についての指針に感謝します。