problem description
the title may not be clear enough, and the problem is described as follows:
I used nodejs + v8.h + libuv to develop a plug-in for nodejs to call a local device driver, in which the function of calling the device to get data uses libuv"s message queue to return data asynchronously. Refer to this from-node-js-part-4-asynchronous-addons/" rel=" nofollow noreferrer "> blog post to implement the callback function, but there is an error in calling the function passed from js in the event callback function (in CPP). Since calling the Call ()
method of Local < Function >
requires passing in an array variable of type Local < Value >
as a parameter, I construct an array argv
as a parameter, but Debugger shows that an error occurs when filling in a value for the argv
array. The error is that a pointer with the value of 0xFFFFFFFFFFFFFFFF
is passed into the constructor of Local < Value >
. As shown in the following picture:
map according to the error function stack (stack order):
1.
2.
3.
the environmental background of the problems and what methods you have tried
OS version: Windows server 2016 Datacenter
nodejs version: v8.12.0
node-gyp version: v3.8.0
Compiler: msvc 15
related codes
// Public data struct for worker thread & main thread
typedef struct R {
int code;
bool fake;
char * string;
R(): code(0), fake(false), string("")
{}
~R() {
delete [] string;
}
} Response;
typedef struct C {
uv_work_t request;
HANDLE deviceHandle;
bool ifRunThread;
unsigned char checkFakeFunOn;
unsigned char * picBuffer;
unsigned char picWidth;
unsigned char picHeight;
unsigned int bufferSize;
// Isolate * isolate;
std::vector<Response> responses[4];
Response *response;
Persistent<Function> callback;
C(): deviceHandle(NULL), ifRunThread(false), picBuffer(NULL), response(NULL){}
~C(){
if (picBuffer != NULL)
delete [] picBuffer;
if (response != NULL)
delete response;
}
} CommonConfig;
// Worker function
void ThreadFun(uv_work_t * req) {
CommonConfig * param = (CommonConfig *)(req->data);
Response *res = new Response;
int err;
int t = 0;
// Isolate * isolate = param->isolate;
unsigned int baseSixFourSize = 2 * param->bufferSize;
char *base64buffer = new char[baseSixFourSize];
// Local<Object> res = v8::Object::New(isolate);
while (param->ifRunThread && (t < 6)) {
// Do something.
}
tPP;
Sleep(1000);
}
if (t >= 6) {
res->code = ERR_TIMEOUT;
param->response = res;
}
if (!param->ifRunThread) {
res->code = ERR_BREAK;
param->response = res;
}
}
// Callback
void callBack(uv_work_t * req, int status) {
std::cout << "callback: fun" << endl;
CommonConfig * params = static_cast<CommonConfig *>(req->data);
Response * resData = params->response;
const unsigned argc = 1;
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
Local<Object> res = v8::Object::New(isolate);
res->Set(String::NewFromUtf8(isolate, "fake"), Boolean::New(isolate, resData->fake));
res->Set(String::NewFromUtf8(isolate, "code"), Number::New(isolate, resData->code));
res->Set(String::NewFromUtf8(isolate, "string"), String::NewFromUtf8(isolate, resData->string));
// The next line code can cause crash:
Local<Value> argv[] = { res };
Local<Function>::New(isolate, params->callback)->Call(isolate->GetCurrentContext()->Global(), argc, argv);
delete params->response;
params->callback.Reset();
delete params;
}
// Function for Js call.
void getFingerPrint(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
Local<Object> res = v8::Object::New(isolate);
if (args.Length() < 1 || !args[0]->IsFunction()) {
res->Set(String::NewFromUtf8(isolate, "code"), Number::New(isolate, ERR_INVALID_PARAM));
args.GetReturnValue().Set(res);
return;
}
globalConfig->request.data = &globalConfig;
globalConfig->callback.Reset(isolate, Local<Function>::Cast(args[0]));
if (globalConfig->ifRunThread) {
res->Set(String::NewFromUtf8(isolate, "code"), Number::New(isolate, ERR_BUSY));
args.GetReturnValue().Set(res);
return;
}
globalConfig->ifRunThread = true;
uv_queue_work(uv_default_loop(), &(globalConfig->request),(uv_work_cb)ThreadFun, (uv_after_work_cb)callBack);
res->Set(String::NewFromUtf8(isolate, "code"), Number::New(isolate, ERR_OK));
args.GetReturnValue().Set(res);
}