2017-09-14 118 views
2

我有一個用C++編寫的使用Nan編寫的Node.js插件。奇妙地工作。但是,我一直無法弄清楚如何讓Node Node代碼將任意數據對象(例如{attr1:42, attr2:'hi', attr3:[5,4,3,2,1]})傳遞給C++插件。將任意Javascript數據對象傳遞給Node.js C++ addon

到現在爲止,我通過調用JSON.stringify()來解決數據對象,然後解析C++端的字符串化JSON。

理想情況下,我想避免複製數據,並先手,我可以訪問,或者至少是本地複製,並避免字符串化/解析數據對象的引用......

任何幫助不勝感激!

+0

請問[幫助?](https://nodeaddons.com/c-processing-from-node-js-part-3-arrays/) –

回答

3

您不必將您的對象串化爲將其傳遞給C++插件。有辦法接受這些任意對象。但它並非如此肆意。你必須編寫不同的代碼來解析C++中的對象。 將其視爲數據庫的模式。您不能將單個集合/表格中的不同格式數據保存。 您將需要具有特定模式的另一個表/集合。

讓我們來看看這個例子:

我們將傳遞一個對象{X:10,Y:5}附加組件,以及C++插件將返回另一個目的與 屬性這樣的和與積:{X1 :15,Y1:50}

在CPP代碼:

NAN_METHOD(func1) { 
     if (info.Length() > 0) { 
       Local<Object> obj = info[0]->ToObject(); 
       Local<String> x = Nan::New<String>("x").ToLocalChecked(); 
       Local<String> y = Nan::New<String>("y").ToLocalChecked(); 

       Local<String> sum = Nan::New<String>("sum").ToLocalChecked(); 
       Local<String> prod = Nan::New<String>("prod").ToLocalChecked(); 

       Local<Object> ret = Nan::New<Object>(); 

       double x1 = Nan::Get(obj, x).ToLocalChecked()->NumberValue(); 
       double y1 = Nan::Get(obj, y).ToLocalChecked()->NumberValue(); 

       Nan::Set(ret, sum, Nan::New<Number>(x1 + y1)); 
       Nan::Set(ret, prod, Nan::New<Number>(x1 * y1)); 

       info.GetReturnValue().Set(ret); 

     } 
} 

在JavaScript的::

const addon = require('./build/Release/addon.node'); 
var obj = addon.func1({ 'x': 5, 'y': 10 }); 
console.log(obj); // { sum: 15, prod: 50 } 

在這裏,你只能發送{x: (Number), y: (number)}類型的對象只有插件。否則它將無法解析或檢索數據。

喜歡本作的數組:

在CPP:

NAN_METHOD(func2) { 
    Local<Array> array = Local<Array>::Cast(info[0]); 

    Local<String> ss_prop = Nan::New<String>("sum_of_squares").ToLocalChecked(); 
    Local<Array> squares = New<v8::Array>(array->Length()); 
    double ss = 0; 

    for (unsigned int i = 0; i < array->Length(); i++) { 
     if (Nan::Has(array, i).FromJust()) { 
     // get data from a particular index 
     double value = Nan::Get(array, i).ToLocalChecked()->NumberValue(); 

     // set a particular index - note the array parameter 
     // is mutable 
     Nan::Set(array, i, Nan::New<Number>(value + 1)); 
     Nan::Set(squares, i, Nan::New<Number>(value * value)); 
     ss += value*value; 
     } 
    } 
    // set a non index property on the returned array. 
    Nan::Set(squares, ss_prop, Nan::New<Number>(ss)); 
    info.GetReturnValue().Set(squares); 
} 

在javascript中:

const addon = require('./build/Release/addon.node'); 
var arr = [1, 2, 3]; 
console.log(addon.func2(arr)); //[ 1, 4, 9, sum_of_squares: 14 ] 

這樣,你可以處理的數據類型。如果你想要複雜的對象或操作,你只需要在一個函數中混合使用這些方法並解析數據。

+1

謝謝您的全面回覆。然而,雖然我不確定什麼是stackoverflow規則,我認爲你應該給斯科特弗里斯貸款的片段似乎是從他的博客... – logidelic

+0

是的!這是正確的。我從那個博客學到了它。 –

2

您可以允許您的Node.js C++插件採用任意類型的參數,但您必須明確檢查並處理類型。他是一個簡單的例子函數,演示如何做到這一點:

void args(const Nan::FunctionCallbackInfo<v8::Value>& info) { 

    int i = 0; 
    while (i < info.Length()) { 
     if (info[i]->IsBoolean()) { 
      printf("boolean = %s", info[i]->BooleanValue() ? "true" : "false"); 
     } else if (info[i]->IsInt32()) { 
      printf("int32 = %ld", info[i]->IntegerValue()); 
     } else if (info[i]->IsNumber()) { 
      printf("number = %f", info[i]->NumberValue()); 
     } else if (info[i]->IsString()) { 
      printf("string = %s", *v8::String::Utf8Value(info[i]->ToString())); 
     } else if (info[i]->IsObject()) { 
      printf("[object]"); 
      v8::Local<v8::Object> obj = info[i]->ToObject(); 
      v8::Local<v8::Array> props = obj->GetPropertyNames(); 
      for (unsigned int j = 0; j < props->Length(); j++) { 
       printf("%s: %s", 
         *v8::String::Utf8Value(props->Get(j)->ToString()), 
         *v8::String::Utf8Value(obj->Get(props->Get(j))->ToString()) 
        ); 
      } 
     } else if (info[i]->IsUndefined()) { 
      printf("[undefined]"); 
     } else if (info[i]->IsNull()) { 
      printf("[null]"); 
     } 
     i += 1; 
    } 
} 

要真正解決處理可能包含任意數據對象任意參數的問題,我建議寫一個解析實際對象的函數類似於我在本例中解析函數參數的方式。請記住,如果您希望能夠處理對象內的嵌套對象,則可能需要遞歸執行此操作。

+1

這是一個很好的例子,但添加一個數組會使它更好。目前尚不清楚OP爲何未接受答案。如果我可以的話我會。 – bmacnaughton

+0

謝謝。你總是可以upvote :-) – mkrufky

+0

我已經做了:)。如果我能再次我會。 – bmacnaughton