将任意的JavaScript数据对象传递到Node.js C 插件

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

本文关键字:Node js 插件 任意 JavaScript 数据 对象      更新时间:2023-10-16

i使用NAN用C 编写的node.js addon。奇妙的作品。但是,我无法弄清楚如何让我的节点JavaScript代码将任意数据对象(ex。{attr1:42, attr2:'hi', attr3:[5,4,3,2,1]})传递给C 插件。

直到现在,我通过在我的数据对象上调用JSON.stringify(),然后在C 方面解析串联的JSON。

理想情况下,我想避免复制数据,并获得对我可以访问的数据对象的引用,或者至少要本地复制它,然后避免使用串联/解析...

任何帮助将不胜感激!

您可以允许您的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;
    }
}

实际解决了可能包含具有任意数据的对象的pontumary 参数的问题,我建议编写一个函数,该函数分析一个实际对象,类似于我在本示例中解析函数参数的方式。请记住,如果您想能够处理对象中的嵌套对象,则可能需要递归地执行此操作。

您不必将对象串起即可将其传递给C 插件。有方法可以接受arbitary对象。但这不是那么arbit。您必须编写不同的代码才能在C 中解析对象。将其视为数据库的模式。您无法将不同的格式数据保存在单个集合/表中。您将需要另一个具有特定架构的表/集合。

让我们看看这个示例:

我们将将对象{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)}键入对象仅发送到addon。否则它将无法解析或检索数据。

喜欢这个数组:

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

这样,您可以处理数据类型。如果您想要复杂的对象或操作,则只是必须将这些方法混合在一个函数中并解析数据。