尝试检索时通过 nan returns undefined 传递数组
Passing an Array via nan returns undefined when attempting to retrieve
我目前正在使用他们的 c++/v8 系统为 NodeJS 编写本机插件,并试图将数组从 Javascript 写入 C++,然后再检索它。每当我尝试从数组中检索一个值并 return 它时,它 return 是一个空数组——因为我最近正在研究 C++,我不确定这是否是我的误解 pointers/c ++ 基础知识或 NodeJS c++ 交互。
我的档案如下:
functions.cc
#include "functions.h"
#include <node.h>
#include <nan.h>
using namespace std;
using namespace v8;
NAN_METHOD(nothing) {
}
NAN_METHOD(aString) {
info.GetReturnValue().Set(Nan::New("This is a thing.").ToLocalChecked());
}
NAN_METHOD(aBoolean) {
info.GetReturnValue().Set(false);
}
NAN_METHOD(aNumber) {
info.GetReturnValue().Set(1.75);
}
NAN_METHOD(anObject) {
v8::Local<v8::Object> obj = Nan::New<v8::Object>();
Nan::Set(obj, Nan::New("key").ToLocalChecked(), Nan::New("value").ToLocalChecked());
info.GetReturnValue().Set(obj);
}
NAN_METHOD(anArray) {
v8::Local<v8::Array> arr = Nan::New<v8::Array>(3);
Nan::Set(arr, 0, Nan::New(1));
Nan::Set(arr, 1, Nan::New(2));
Nan::Set(arr, 2, Nan::New(3));
info.GetReturnValue().Set(arr);
}
NAN_METHOD(callback) {
v8::Local<v8::Function> callbackHandle = info[0].As<v8::Function>();
Nan::MakeCallback(Nan::GetCurrentContext()->Global(), callbackHandle, 0, 0);
}
// Wrapper Impl
Nan::Persistent<v8::Function> MyObject::constructor;
NAN_MODULE_INIT(MyObject::Init) {
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
//Nan::SetPrototypeMethod(tpl, "plusOne", PlusOne);
Nan::SetPrototypeMethod(tpl, "getArr", arrY);
Nan::SetPrototypeMethod(tpl, "PassArray", passArray);
Nan::SetPrototypeMethod(tpl, "setArray", SetArray);
constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked());
Nan::Set(target, Nan::New("MyObject").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked());
}
MyObject::MyObject(v8::Local<v8::Array> value) : value_(value) {
}
MyObject::~MyObject() {
}
NAN_METHOD(MyObject::New) {
if (info.IsConstructCall()) {
v8::Local<v8::Array> arr = Nan::New<v8::Array>();
v8::Local<v8::Array> value = v8::Handle<v8::Array>::Cast(arr);
MyObject *obj = new MyObject(value);
obj->Wrap(info.This());
info.GetReturnValue().Set(info.This());
} else {
const int argc = 1;
v8::Local<v8::Value> argv[argc] = {info[0]};
v8::Local<v8::Function> cons = Nan::New(constructor);
info.GetReturnValue().Set(cons->NewInstance(argc, argv));
}
}
// NAN_METHOD(MyObject::PlusOne) {
// MyObject* obj = Nan::ObjectWrap::Unwrap<MyObject>(info.This());
// obj->value_ += 1;
// info.GetReturnValue().Set(obj->value_);
// }
NAN_METHOD(MyObject::SetArray){
Nan::HandleScope scope;
vector<string> result;
Handle<Value> val;
Local<Array> arr = Nan::New<Array>();
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
if (info[0]->IsArray()) {
Handle<Array> jsArray = Handle<Array>::Cast(info[0]);
for (unsigned int i = 0; i < jsArray->Length(); i++) {
val = jsArray->Get(i);
result.push_back(string(*String::Utf8Value(val)));
Nan::Set(arr, i, val);
}
}
info.GetReturnValue().Set(obj->value_);
}
NAN_METHOD(MyObject::arrY){
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
info.GetReturnValue().Set(Local<Array>::Cast(obj->value_));
}
NAN_METHOD(MyObject::passArray) {
Nan::HandleScope scope;
vector<string> result;
Handle<Value> val;
Local<Array> arr = Nan::New<Array>();
if (info[0]->IsArray()) {
Handle<Array> jsArray = Handle<Array>::Cast(info[0]);
for (unsigned int i = 0; i < jsArray->Length(); i++) {
val = jsArray->Get(i);
result.push_back(string(*String::Utf8Value(val)));
Nan::Set(arr, i, val);
}
}
MyObject* obj = Nan::ObjectWrap::Unwrap<MyObject>(info.This());
obj->value_ = arr;
info.GetReturnValue().Set(obj->value_);
}
functions.h
#ifndef NATIVE_EXTENSION_GRAB_H
#define NATIVE_EXTENSION_GRAB_H
#include <nan.h>
// Example top-level functions. These functions demonstrate how to return various js types.
// Implementations are in functions.cc
NAN_METHOD(nothing);
NAN_METHOD(aString);
NAN_METHOD(aBoolean);
NAN_METHOD(aNumber);
NAN_METHOD(anObject);
NAN_METHOD(anArray);
NAN_METHOD(callback);
// Example with node ObjectWrap
// Based on https://nodejs.org/api/addons.html#addons_wrapping_c_objects but using NAN
class MyObject : public Nan::ObjectWrap {
public:
static NAN_MODULE_INIT(Init);
private:
explicit MyObject(v8::Local<v8::Array> value);
~MyObject();
static NAN_METHOD(New);
static NAN_METHOD(PlusOne);
static NAN_METHOD(SetArray);
static NAN_METHOD(arrY);
static NAN_METHOD(passArray);
static Nan::Persistent<v8::Function> constructor;
v8::Local<v8::Array> value_;
};
#endif
index.js
var NativeExtension = require('bindings')('NativeExtension');
module.exports = NativeExtension;
console.log(NativeExtension.aString());
var obj = NativeExtension.MyObject([1,2,3]);
console.log(NativeExtension.aString());
console.log(obj.PassArray([1, 1, 3]));
console.log(obj.getArr());
console.log(obj.setArray())
出于测试目的,代码绝对不是 DRY,它基于通过 github which can be found here.
提供的非精简版 nan-boilerplate 代码
重新阅读我自己的代码后,我可以肯定地说我的方法命名是不好,所以PassArr应该设置一个数组,getArr应该return传递的数组"PassArr"。 SetArray 是我留下的一个骇人听闻的尝试。
重申一下,我试图实现的功能是:
Javascript Array -> C++ variable
C++ variable -> Javascript Array
但当前功能不会保留我的变量。 运行 index.js 的结果如下:
This is a thing.
This is a thing.
[ 1, 1, 3 ]
Console {
log: [Function: bound ],
info: [Function: bound ],
warn: [Function: bound ],
error: [Function: bound ],
dir: [Function: bound ],
time: [Function: bound ],
timeEnd: [Function: bound ],
trace: [Function: bound trace],
assert: [Function: bound ],
Console: [Function: Console] }
[]
迟到总比不到好...这里有两个问题:
首先是MyObject::value_
是本地句柄。它应该是一个永久句柄,您需要在 ~MyObject()
中重置它,否则它会泄漏。
第二个问题是MyObject::passArray
中的数组arr
的长度为0,你应该用正确的长度构造它。
我目前正在使用他们的 c++/v8 系统为 NodeJS 编写本机插件,并试图将数组从 Javascript 写入 C++,然后再检索它。每当我尝试从数组中检索一个值并 return 它时,它 return 是一个空数组——因为我最近正在研究 C++,我不确定这是否是我的误解 pointers/c ++ 基础知识或 NodeJS c++ 交互。
我的档案如下:
functions.cc
#include "functions.h"
#include <node.h>
#include <nan.h>
using namespace std;
using namespace v8;
NAN_METHOD(nothing) {
}
NAN_METHOD(aString) {
info.GetReturnValue().Set(Nan::New("This is a thing.").ToLocalChecked());
}
NAN_METHOD(aBoolean) {
info.GetReturnValue().Set(false);
}
NAN_METHOD(aNumber) {
info.GetReturnValue().Set(1.75);
}
NAN_METHOD(anObject) {
v8::Local<v8::Object> obj = Nan::New<v8::Object>();
Nan::Set(obj, Nan::New("key").ToLocalChecked(), Nan::New("value").ToLocalChecked());
info.GetReturnValue().Set(obj);
}
NAN_METHOD(anArray) {
v8::Local<v8::Array> arr = Nan::New<v8::Array>(3);
Nan::Set(arr, 0, Nan::New(1));
Nan::Set(arr, 1, Nan::New(2));
Nan::Set(arr, 2, Nan::New(3));
info.GetReturnValue().Set(arr);
}
NAN_METHOD(callback) {
v8::Local<v8::Function> callbackHandle = info[0].As<v8::Function>();
Nan::MakeCallback(Nan::GetCurrentContext()->Global(), callbackHandle, 0, 0);
}
// Wrapper Impl
Nan::Persistent<v8::Function> MyObject::constructor;
NAN_MODULE_INIT(MyObject::Init) {
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
//Nan::SetPrototypeMethod(tpl, "plusOne", PlusOne);
Nan::SetPrototypeMethod(tpl, "getArr", arrY);
Nan::SetPrototypeMethod(tpl, "PassArray", passArray);
Nan::SetPrototypeMethod(tpl, "setArray", SetArray);
constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked());
Nan::Set(target, Nan::New("MyObject").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked());
}
MyObject::MyObject(v8::Local<v8::Array> value) : value_(value) {
}
MyObject::~MyObject() {
}
NAN_METHOD(MyObject::New) {
if (info.IsConstructCall()) {
v8::Local<v8::Array> arr = Nan::New<v8::Array>();
v8::Local<v8::Array> value = v8::Handle<v8::Array>::Cast(arr);
MyObject *obj = new MyObject(value);
obj->Wrap(info.This());
info.GetReturnValue().Set(info.This());
} else {
const int argc = 1;
v8::Local<v8::Value> argv[argc] = {info[0]};
v8::Local<v8::Function> cons = Nan::New(constructor);
info.GetReturnValue().Set(cons->NewInstance(argc, argv));
}
}
// NAN_METHOD(MyObject::PlusOne) {
// MyObject* obj = Nan::ObjectWrap::Unwrap<MyObject>(info.This());
// obj->value_ += 1;
// info.GetReturnValue().Set(obj->value_);
// }
NAN_METHOD(MyObject::SetArray){
Nan::HandleScope scope;
vector<string> result;
Handle<Value> val;
Local<Array> arr = Nan::New<Array>();
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
if (info[0]->IsArray()) {
Handle<Array> jsArray = Handle<Array>::Cast(info[0]);
for (unsigned int i = 0; i < jsArray->Length(); i++) {
val = jsArray->Get(i);
result.push_back(string(*String::Utf8Value(val)));
Nan::Set(arr, i, val);
}
}
info.GetReturnValue().Set(obj->value_);
}
NAN_METHOD(MyObject::arrY){
MyObject* obj = ObjectWrap::Unwrap<MyObject>(info.Holder());
info.GetReturnValue().Set(Local<Array>::Cast(obj->value_));
}
NAN_METHOD(MyObject::passArray) {
Nan::HandleScope scope;
vector<string> result;
Handle<Value> val;
Local<Array> arr = Nan::New<Array>();
if (info[0]->IsArray()) {
Handle<Array> jsArray = Handle<Array>::Cast(info[0]);
for (unsigned int i = 0; i < jsArray->Length(); i++) {
val = jsArray->Get(i);
result.push_back(string(*String::Utf8Value(val)));
Nan::Set(arr, i, val);
}
}
MyObject* obj = Nan::ObjectWrap::Unwrap<MyObject>(info.This());
obj->value_ = arr;
info.GetReturnValue().Set(obj->value_);
}
functions.h
#ifndef NATIVE_EXTENSION_GRAB_H
#define NATIVE_EXTENSION_GRAB_H
#include <nan.h>
// Example top-level functions. These functions demonstrate how to return various js types.
// Implementations are in functions.cc
NAN_METHOD(nothing);
NAN_METHOD(aString);
NAN_METHOD(aBoolean);
NAN_METHOD(aNumber);
NAN_METHOD(anObject);
NAN_METHOD(anArray);
NAN_METHOD(callback);
// Example with node ObjectWrap
// Based on https://nodejs.org/api/addons.html#addons_wrapping_c_objects but using NAN
class MyObject : public Nan::ObjectWrap {
public:
static NAN_MODULE_INIT(Init);
private:
explicit MyObject(v8::Local<v8::Array> value);
~MyObject();
static NAN_METHOD(New);
static NAN_METHOD(PlusOne);
static NAN_METHOD(SetArray);
static NAN_METHOD(arrY);
static NAN_METHOD(passArray);
static Nan::Persistent<v8::Function> constructor;
v8::Local<v8::Array> value_;
};
#endif
index.js
var NativeExtension = require('bindings')('NativeExtension');
module.exports = NativeExtension;
console.log(NativeExtension.aString());
var obj = NativeExtension.MyObject([1,2,3]);
console.log(NativeExtension.aString());
console.log(obj.PassArray([1, 1, 3]));
console.log(obj.getArr());
console.log(obj.setArray())
出于测试目的,代码绝对不是 DRY,它基于通过 github which can be found here.
提供的非精简版 nan-boilerplate 代码重新阅读我自己的代码后,我可以肯定地说我的方法命名是不好,所以PassArr应该设置一个数组,getArr应该return传递的数组"PassArr"。 SetArray 是我留下的一个骇人听闻的尝试。
重申一下,我试图实现的功能是:
Javascript Array -> C++ variable
C++ variable -> Javascript Array
但当前功能不会保留我的变量。 运行 index.js 的结果如下:
This is a thing.
This is a thing.
[ 1, 1, 3 ]
Console {
log: [Function: bound ],
info: [Function: bound ],
warn: [Function: bound ],
error: [Function: bound ],
dir: [Function: bound ],
time: [Function: bound ],
timeEnd: [Function: bound ],
trace: [Function: bound trace],
assert: [Function: bound ],
Console: [Function: Console] }
[]
迟到总比不到好...这里有两个问题:
首先是MyObject::value_
是本地句柄。它应该是一个永久句柄,您需要在 ~MyObject()
中重置它,否则它会泄漏。
第二个问题是MyObject::passArray
中的数组arr
的长度为0,你应该用正确的长度构造它。