1

I am trying to write a native C++ module to include in a Node.js project -- I followed the guide here and have things setup pretty well.

The general idea is that I want to pass an array of integers to my C++ module to be sorted; the module then returns the sorted array.

However, I cannot compile using node-gyp build because I hit the following error:

error: no viable conversion from 'Local' to 'int *'

It is complaining about this code in my C++:

void Method(const FunctionCallbackInfo<Value>& args) {
    Isolate* isolate = args.GetIsolate();

    int* inputArray = args[0]; // <-- ERROR!

    sort(inputArray, 0, sizeof(inputArray) - 1);

    args.GetReturnValue().Set(inputArray);
}

This all makes conceptual sense to me -- the compiler can't magically cast arg[0] (presumably of type v8::Local) to an int*. Having said that, I cannot seem to find any way to get my argument successfully cast into a C++ integer array.

It should be known that my C++ is rather rusty, and I know next-to-nothing about V8. Can anyone point me in the right direction?

1 Answer 1

2

It's not trivial: you first need to unpack the JS array (internally represented as a v8::Array) into something sortable (like a std::vector), sort it, and convert it back to a JS array.

Here's an example:

void Method(const FunctionCallbackInfo<Value>& args) {
    Isolate* isolate = args.GetIsolate();

    // Make sure there is an argument.
    if (args.Length() != 1) {
        isolate->ThrowException(Exception::TypeError(
            String::NewFromUtf8(isolate, "Need an argument")));
        return;
    }

    // Make sure it's an array.
    if (! args[0]->IsArray()) {
        isolate->ThrowException(Exception::TypeError(
            String::NewFromUtf8(isolate, "First argument needs to be an array")));
        return;
    }

    // Unpack JS array into a std::vector
    std::vector<int> values;
    Local<Array> input = Local<Array>::Cast(args[0]);
    unsigned int numValues = input->Length();
    for (unsigned int i = 0; i < numValues; i++) {
        values.push_back(input->Get(i)->NumberValue());
    }

    // Sort the vector.
    std::sort(values.begin(), values.end());

    // Create a new JS array from the vector.
    Local<Array> result = Array::New(isolate);
    for (unsigned int i = 0; i < numValues; i++ ) {
        result->Set(i, Number::New(isolate, values[i]));
    }

    // Return it.
    args.GetReturnValue().Set(result);
}

Disclaimer: I'm not a v8 wizard, nor a C++ one, so there may be better ways to do this.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.