nodejs C++ addon的异步回调函数里为什么不能构造Local数组?
问题描述
标题可能不够清晰,问题描述如下:
我使用 nodejs + v8.h + libuv 开发了一个用于nodejs调用本地一设备驱动的插件, 其中调用设备获取数据的函数使用了libuv的消息队列实现异步返回数据. 参考这篇博文实现了回调功能,然而在事件回调函数(in C++)里调用从js传入的函数时却遇到了错误. 由于调用Local<Function>
的Call()
方法需要传入一个Local<Value>
型的数组变量作为参数, 所以我构造了一个数组argv
作为参数, 但是Debugger显示在为argv
数组填入值时会发生错误, 错误表现是在Local<Value>
的构造函数里传入了一个值为0xFFFFFFFFFFFFFFFF
的指针. 如下述图片示:
按照出错函数栈(入栈序)贴图:
1.
2.
3.
问题出现的环境背景及自己尝试过哪些方法
OS 版本: Windows server 2016 Datacenter
nodejs 版本: v8.12.0
node-gyp 版本: v3.8.0
编译器: msvc 15
相关代码
// 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.
}
t++;
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);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论