将任意Javascript数据对象传递给Node.js C ++插件

我有一个用C ++编写的使用Nan的Node.js插件。 奇妙地工作。 然而,我一直没能弄清楚如何让我的节点的Javascript代码传递任意的数据对象(例如{attr1:42, attr2:'hi', attr3:[5,4,3,2,1]} )到C ++插件。

直到现在,我已经通过调用我的数据对象的JSON.stringify()来解决这个问题,然后parsingC ++端的string化的JSON。

理想情况下,我想避免复制数据,只是获得我可以访问的数据对象的引用,或者至less要本地复制它,并避免string化/parsing…

任何帮助,将不胜感激!

你不必把你的对象串起来传递给c ++插件。 有办法接受这些仲裁对象。 但它并不是那么恣意的。 你必须编写不同的代码来parsingc ++中的对象。 把它看作是一个数据库的模式。 您不能在一个集合/表格中保存不同的格式数据。 您将需要具有特定模式的另一个表/集合。

我们来看看这个例子:

我们将一个对象{x:10,y:5}传递给addon,而c ++ addon将会返回另一个对象,它们的属性如下所示:{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)}types的对象发送给addon。 否则它将无法parsing或检索数据。

像这样的arrays:

在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 ] 

像这样,你可以处理数据types。 如果你想要复杂的对象或操作,你只需要在一个函数中混合这些方法并parsing数据。

您可以允许您的Node.js c ++插件采取任意types的参数,但您必须明确地检查和处理types。 他是一个简单的示例函数,显示如何做到这一点:

 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]"); } } } 

要真正解决处理可能包含任意数据对象的任意参数的问题,我build议编写一个函数来parsing一个类似于我在本例中parsing函数参数的实际对象。 请记住,如果您希望能够处理对象内的嵌套对象,则可能需要recursion执行此操作。