nodejs C++ addon的异步回调函数里为什么不能构造Local数组?

发布于 2022-09-11 14:47:24 字数 4792 浏览 17 评论 0

问题描述

标题可能不够清晰,问题描述如下:
我使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文