2013-04-22 12 views
1

저는 C++ 래퍼를 사용하는 Nodej 모듈을 개발하는 데 필요한 기술을보다 잘 이해하려고합니다. 나는 찾을 수있는 많은 정보를 가지고 일하고있다. 예를 들면 Nodejs Documentation.C++ 래퍼를 사용하여 Nodejs 모듈에 인수 전달?

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; 

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이 어디 내 이해를 밀어 나는 유사한 방법으로 사용될 수있는 Nodejs 모듈을 작성하는 과제를 설정 C++ 래퍼를 사용하여 Stack Overflow 게시했지만 매개 변수를 상속 된 클래스에 추가하면 인수가 기본 클래스로 전달되지 않습니다. 많은 솔루션을 시도했지만 상속 (부모 처리) 함수에 대한 내 이해가 잘못되었다고 생각합니다. 이 코드는 다음과 같다 :

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) 

코드에 몇 가지 주석을 추가하여 문제의 위치를 ​​나타냅니다.

내가 잘못 가고있는 곳의 포인터에 감사드립니다.

답변

0

처음에는 일의 JS면에 대한 이해가 내가 먼저 정리하고 싶은 약간의 오해가 있다고 생각합니다.

Grapes.prototype = new Fruit(); 

은 당신의 Fruit 함수는 두 개의 인수를 취하더라도, 인수없이 한 번 한 번만 Fruit 생성자를 실행하기 때문에, 이것에 대해 갈 수있는 좋은 방법이 아니다. Grapes

var util = require('util'); 
util.inherits(Grapes, Fruit); 

// or this if you want to do it manually. 
function GrapesProto(){} 
GrapesProto.prototype = Fruit; 
Grapes.prototype = new GrapesProto(); 

Fruit 슈퍼 생성자를 호출 건설이 효과적으로

Grapes.prototype.__proto__ = Fruit; 
Grapes.prototype.weight = undefined; 
Grapes.prototype.calories = undefined; 

당신이 정말로 다음과 같이 수행됩니다 첫 번째 줄입니다 원하는 모든 작업을 수행합니다. 그와 지금

function Grapes(number, weight, calories) { 
    this.number = number; 

    // Call the 'super' constructor. 
    Fruit.call(this, weight, calories); 
} 

는 길에서, 나는 그것이 유일한 방법으로 당신이 C++에서이 작업을하기 위해, Grapes 실제로 표준 C++ 상속을 사용하여 Fruit을 확장해야 좀 더 명확한 생각이 당신이 할 수있는 올바른 super 전화를하십시오.

class Grapes : public Fruit { 

또한 만들 것입니다 귀하의 GrapesFruit은 JS 위가처럼 슈퍼를 통해 전화 기본이 아닌 생성자를 가지고있다.당신은 각 Grapes 객체가 가중치와 칼로리 값을 가질 것으로 기대하며,이 값이 없으면 그렇지 않습니다. 그리고 C++에서 상속 된 템플릿 함수를 Fruit에서 호출 할 수 있기를 원하면 Grapes 개체를 Fruit으로 사용할 수 있어야합니다. 즉, 하위 클래스 여야합니다. 그래서 기본적으로

:

Handle<Value> Grapes::New(const Arguments& args){ 
    double weight = args[0]->IsUndefined() ? 0 : args[0]->NumberValue(); 
    double calories = args[1]->IsUndefined() ? 0 : args[1]->NumberValue(); 
    double number = args[2]->IsUndefined() ? 0 : args[2]->NumberValue(); 
    Grapes* obj = new Grapes(number, weight, calories); 

// AND 

Grapes::Grapes(int number, double weight, double calories) 
    : Fruit(weight, calories), number_(number) {}; 

과 거의 거울 Fruit 그.

+0

내 질문에 대한 귀하의 훌륭한 답변에 감사드립니다. 나는 JS에 익숙하지 않아 배경에서 무슨 일이 일어나고 있는지에 대한 당신의 설명을 발견했다. 저는 C++ 구현에 대한 지침을 통해 작업했으며 JS에 대한보다 명확한 이해로 모든 것이 작동합니다. 당신의 도움을 주셔서 감사합니다. – David