gpt4 book ai didi

node.js - 使用 C++ 包装器将参数传递给 Nodejs 模块?

转载 作者:太空宇宙 更新时间:2023-11-04 02:40:50 26 4
gpt4 key购买 nike

我正在尝试更好地理解开发使用 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;

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)

我在代码中添加了一些注释来表明我认为问题出在哪里。

感谢任何指出我哪里出错的地方。

最佳答案

首先,我认为您对 JS 方面的理解有一个轻微的误解,我想首先澄清这一点。

Grapes.prototype = new Fruit();

不是一个好方法,因为这将在不带参数的情况下执行一次 Fruit 构造函数一次且仅一次,即使您的 Fruit 函数需要两个参数。这有效地做到了

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

您真正想要的只是第一行,它是这样完成的:

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 super 构造函数构造 Grapes

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 一样调用 super 。您的实现期望每个 Grapes 对象都有一个重量和卡路里值,如果没有这个,情况就不会是这样。如果您希望能够在 C++ 中调用从 Fruit 继承的模板函数,那么它需要能够将 Grapes 对象作为 Fruit 进行Unwrap,这意味着它需要是一个子类。

所以基本上:

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的情况大致相同。

关于node.js - 使用 C++ 包装器将参数传递给 Nodejs 模块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16155235/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com