在尝试检索时,通过nan传递数组返回undefined

时间:2016-07-28 14:53:31

标签: c++ node.js v8 node.js-addon node.js-nan

我目前正在使用他们的c ++ / v8系统为NodeJS编写一个本机插件,并且我正在尝试从Javascript编写一个数组,再到C ++,然后检索它。每当我尝试从数组中检索一个值并返回它时,它返回一个空数组 - 因为我最近潜入c ++我不确定这是我的误解指针/ 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应该返回“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] }
[]

1 个答案:

答案 0 :(得分:1)

迟到总比没有......这里有两个问题:

首先,MyObject::value_是本地句柄。它应该是一个持久句柄,您需要在~MyObject()中重置,否则它将泄漏。

第二个问题是arr中的数组MyObject::passArray的长度为0,您应该使用正确的长度构建它。