简体   繁体   English

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

[英]Pass arbitrary Javascript data object to Node.js C++ addon

I have a Node.js addon written in C++ using Nan. 我有一个使用Nan用C ++编写的Node.js插件。 Works fantastically. 工作非常好。 However, I've not been able to figure out how to have my Node Javascript code pass an arbitrary data object (ex. {attr1:42, attr2:'hi', attr3:[5,4,3,2,1]} ) to the C++ addon. 但是,我无法弄清楚如何让我的Node Javascript代码传递任意数据对象(例如{attr1:42, attr2:'hi', attr3:[5,4,3,2,1]} )到C ++插件。

Until now, I've got around this by calling JSON.stringify() on my data object and then parsing the stringified JSON on the C++ side. 到目前为止,我通过在我的数据对象上调用JSON.stringify()然后在C ++端解析字符串化的JSON来解决这个问题。

Ideally, I'd like to avoid copying data and just get a reference to the data object that I can access, or at least to copy it natively and avoid stringifying/parsing... 理想情况下,我想避免复制数据,只是获取对我可以访问的数据对象的引用,或者至少本地复制它并避免字符串化/解析...

Any help would be appreciated! 任何帮助,将不胜感激!

You can allow your Node.js c++ addons to take arbitrary typed arguments, but you must check and handle the types explicitly. 您可以允许Node.js c ++插件采用任意类型的参数,但必须明确检查和处理类型。 He is a simple example function that shows how to do this: 他是一个简单的示例函数,展示了如何执行此操作:

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;
    }
}

To actually solve the problem of handling arbitrary arguments that may contain objects with arbitrary data, I would recommend writing a function that parses an actual object similar to how I parsed function arguments in this example. 为了实际解决处理可能包含具有任意数据的对象的任意参数的问题,我建议编写一个解析实际对象的函数,类似于我在此示例中解析函数参数的方式。 Keep in mind that you may need to do this recursively if you want to be able to handle nested objects within the object. 请记住,如果您希望能够处理对象中的嵌套对象,则可能需要递归执行此操作。

You don't have to stringify your object to pass it to c++ addons. 您不必将对象字符串化以将其传递给c ++插件。 There are methods to accept those arbitary objects. 有接受这些仲裁对象的方法。 But it is not so arbitary. 但它不是那么随意。 You have to write different codes to parse the object in c++ . 您必须编写不同的代码来解析c ++中的对象。 Think of it as a schema of a database. 将其视为数据库的模式。 You can not save different format data in a single collection/table. 您无法在单个集合/表中保存不同的格式数据。 You will need another table/collection with the specific schema. 您将需要具有特定架构的另一个表/集合。

Let's see this example: 我们来看看这个例子:

We will pass an object {x: 10 , y: 5} to addon, and c++ addon will return another object with sum and product of the properties like this: {x1:15,y1: 50} 我们将对象{x:10,y:5}传递给addon,c ++ addon将返回另一个对象,其中包含属性的sum和product,如下所示:{x1:15,y1:50}

In cpp code : 在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);

        }
}

In javascript:: 在javascript ::

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

Here you can only send {x: (Number), y: (number)} type object to addon only. 在这里,您只能将{x: (Number), y: (number)}类型对象仅发送到插件。 Else it will not be able to parse or retrieve data. 否则它将无法解析或检索数据。

Like this for the array: 像这样的数组:

In cpp: 在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);
}

In javascript: 在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 ]

Like this, you can handle data types. 像这样,您可以处理数据类型。 If you want complex objects or operations, you just have to mix these methods in one function and parse the data. 如果需要复杂的对象或操作,只需在一个函数中混合使用这些方法并解析数据即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM