I want to access the elements of an array that is passed in a function as an arg from the js side.
The code is like this:
void Method(const FunctionCallbackInfo<Value> &args){
Isolate* isolate = args.GetIsolate();
Local<Array> array = Local<Array>::Cast(args[0]);
for(int i=0;i<(int)array->Length();i++){
auto ele = array->Get(i);
}
I'm getting this error:
error: no matching function for call to ‘v8::Array::Get(int&)’
After reading the implementation of the V8 Array and I get to know that there is no Get method for Array.
Here is the implementation of Array in the v8 source code:
class V8_EXPORT Array : public Object {
public:
uint32_t Length() const;
/**
* Creates a JavaScript array with the given length. If the length
* is negative the returned array will have length 0.
*/
static Local<Array> New(Isolate* isolate, int length = 0);
/**
* Creates a JavaScript array out of a Local<Value> array in C++
* with a known length.
*/
static Local<Array> New(Isolate* isolate, Local<Value>* elements,
size_t length);
V8_INLINE static Array* Cast(Value* obj);
private:
Array();
static void CheckCast(Value* obj);
};
I'm new to v8 lib. I walked through some tutorials and it was working fine for them. Can anyone help me to figure out what's wrong with it? If we can't use Local<Array> then what else is there which can fulfill this purpose?
Hard to answer without knowing which exact version of v8 you're targeting, but in the current doxygen documentation there are two overloads for v8::Object::Get:
MaybeLocal< Value > Get (Local< Context > context, Local< Value > key)
MaybeLocal< Value > Get (Local< Context > context, uint32_t index)
So I think you can do the following:
Local<Context> ctx = isolate->GetCurrentContext();
auto ele = array->Get(ctx, i);
...
Related
I want to access the elements of an array that is passed in a function as an arg from the js side.
The code is like this:
void Method(const FunctionCallbackInfo<Value> &args){
Isolate* isolate = args.GetIsolate();
Local<Array> array = Local<Array>::Cast(args[0]);
for(int i=0;i<(int)array->Length();i++){
auto ele = array->Get(i);
}
I'm getting this error:
error: no matching function for call to ‘v8::Array::Get(int&)’
After reading the implementation of the V8 Array and I get to know that there is no Get method for Array.
Here is the implementation of Array in the v8 source code:
class V8_EXPORT Array : public Object {
public:
uint32_t Length() const;
/**
* Creates a JavaScript array with the given length. If the length
* is negative the returned array will have length 0.
*/
static Local<Array> New(Isolate* isolate, int length = 0);
/**
* Creates a JavaScript array out of a Local<Value> array in C++
* with a known length.
*/
static Local<Array> New(Isolate* isolate, Local<Value>* elements,
size_t length);
V8_INLINE static Array* Cast(Value* obj);
private:
Array();
static void CheckCast(Value* obj);
};
I'm new to v8 lib. I walked through some tutorials and it was working fine for them. Can anyone help me to figure out what's wrong with it? If we can't use Local<Array> then what else is there which can fulfill this purpose?
Hard to answer without knowing which exact version of v8 you're targeting, but in the current doxygen documentation there are two overloads for v8::Object::Get:
MaybeLocal< Value > Get (Local< Context > context, Local< Value > key)
MaybeLocal< Value > Get (Local< Context > context, uint32_t index)
So I think you can do the following:
Local<Context> ctx = isolate->GetCurrentContext();
auto ele = array->Get(ctx, i);
...
Prehistory: I am creating template class(HashMap< KeyType, ValueType >), which should implement abstraction of map using hash tables. To solve collisions in hash tables method of chains is used. I get error when I attempt to initialize HashMap object in main.cpp using constructor HashMap().
Error: "stack cookie instrumentation code detected a stack-based
buffer overrun."
So, the code:
Part of private section(only all member variables and method createBuckets(), which is used in constructor HashMap())
private:
/* Constant definitions */
static const int INITIAL_BUCKET_COUNT = 101;
static const int MAX_LOAD_PERCENTAGE = 70;
/* Type definition for cells in the bucket chain */
struct Cell {
KeyType key;
ValueType value;
Cell *next;
};
/* Instance variables */
vector<Cell *> buckets;
int nBuckets;
int numEntries;
/* Private methods */
/*
* Private method: createBuckets
* Usage: createBuckets(nBuckets);
* -------------------------------
* Sets up the vector of buckets to have nBuckets entries, each NULL. If
* asked to make empty vector, makes one bucket just to simplify handling
* elsewhere.
*/
void createBuckets(int new_nBuckets) {
if (new_nBuckets == 0) nBuckets = 1;
buckets = vector<Cell *>(new_nBuckets, NULL);
this->nBuckets = new_nBuckets;
numEntries = 0;
}
template <typename KeyType, typename ValueType>
HashMap<KeyType, ValueType>::HashMap() {
createBuckets(INITIAL_BUCKET_COUNT);
}
The most strange that the error happens rarely and when it does not happen, class works successufully. If I recompile the programm, there is no error and it do not happen until the next recompling. If it can matter, I use Visual Studia 2017 for writing this programm.
I suppose that problem is caused by creating of vector in method createBuckets, but I can not see any problem with this.
I am trying to create a basic native node addon where a javascript array is passed from node and then processed in c++. The problem is I cannot figure out how to correctly pass the array. I can instantiate the array without issue but assigning it using info[0].as throws errors.
My c++ code is
#include <napi.h>
using namespace Napi;
using namespace std;
Value Add(const CallbackInfo& info)
{
Env env = info.Env();
Array result = Napi::Array::New(env);
Array a = info[0].As<Array>;
double arg1 = info[1].As<Number>().DoubleValue();
Number num = Napi::Number::New(env, 2 + arg1);
return num;
}
The error I am getting is
../cppsrc/main.cpp: In function ‘Napi::Value Add(const Napi::CallbackInfo&)’:
../cppsrc/main.cpp:12:21: error: conversion from ‘<unresolved overloaded function type>’ to non-scalar type ‘Napi::Array’ requested
Array a = info[0].As<Array>;
~~~~~~~~^~~~~~~~~
What is the correct way to pass an array to c++? Is it even possible?
This works for me:
void runSetPropertyAsyncWorker(const CallbackInfo& info)
{
std::string path = info[0].As<Napi::String>();
int property = info[1].As<Number>();
int dataSize = info[2].As<Number>();
Array b = info[3].As<Array>();
for(int i = 0; i<b.Length(); i++)
{
Napi::Value v = b[i];
if (v.IsNumber())
{
int value = (int)v.As<Napi::Number>();
...
...
}
}
...
...
Function callback = info[4].As<Function>();
AsyncWorker* asyncWorker = new SetPropertyAsyncWorker(callback, ...);
asyncWorker->Queue();
}
Use Napi::Object. Napi::Array is actually inherited from Napi::Object.
You could replace the code Array a = info[0].As<Array>; with Array a = info[0].ToObject();.
You can then access the data members via Value
operator[] (uint32_t index) const
Source: https://nodejs.github.io/node-addon-api/class_napi_1_1_object.html
Edit: Bonus feature, if an argument that is not an object is passed, this will automatically trigger an Error: Object Expected.
error code here:
Array a = info[0].As<Array>;
which should be
Array a = info[0].As<Array>();
I was not able to find a solution to the actual question of interacting with the Javascript object directly with node-addon-api. The Solution that I chose to go with is JSON.stringify any arrays or objects and then parse then in c++ is a library called rapid json. This proves to be the only way to interface with javascript objects that i've been able to find
I have the following situation.
I need to insert certain CallInst in my code.
The prototype of my function is
void __llvmFooBar(int data, int loc);
The parameter loc is generated by the pass. I don't need any external data to generate that.
But, the parameter data is basically calculated by using some variable declared inside my C-code.
//test.c
int main()
{
int k = 0;
happyEnding(k);
}
void happyEnding(int k)
{
int __data = seed(time()) + k%2;
//callInst to be inserted here, it should be
//__llvmFooBar(__data, 23);
myAlgorithim();
}
//pass.cpp
......
std::vector<Value *> args(2);
args[0] = ??? //need help here
args[1] = ConstantInt::get(IntegerTy, getLoc());
m_builder->CreateCall(hook, args);
In generic sense, how to make all variable with specific naming convention(like starts with __) make available to llvm pass ?
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?
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.