使用node-nan

时间:2015-11-25 23:39:21

标签: c++ node.js node-gyp node.js-addon node.js-nan

我正在尝试创建一个可以使用全局键绑定执行某些功能的Electron node.js应用程序。不幸的是,Electron中的全局键绑定API在游戏中不起作用,因此我需要创建一个侦听这些低级别键事件的本机节点模块。

所以我使用node-gyp用visual studio 2015和nan编译项目,以提供节点和c ++之间的通信。我已经设法让项目的两个方面单独工作(低级键绑定和node.js< - > nan通信)但我在组合它们时遇到了麻烦。我也承认我对c ++的经验很少(我没有编写过单一的c ++程序)。

#include "node_modules/nan/nan.h"

using namespace std;
using namespace Nan;

HHOOK _hook;
KBDLLHOOKSTRUCT kbdStruct;

class KeyboardEventWorker : public AsyncProgressWorker {
 public:
  KeyboardEventWorker(Callback *callback, Callback *progress)
    : AsyncProgressWorker(callback), progress(progress) {}
  ~KeyboardEventWorker() {}

  LRESULT CALLBACK HookCallback(int nCode,WPARAM wParam,LPARAM lParam) {  
    executionProgress->Send(reinterpret_cast<const char*>(nCode), sizeof(nCode));
    return CallNextHookEx(_hook, nCode, wParam, lParam);
  }

  void Execute (const AsyncProgressWorker::ExecutionProgress& progress) {
    executionProgress = &progress; //PROBLEM #1
        _hook = SetWindowsHookEx(13, HookCallback, NULL, 0); //PROBLEM #2

    SleepEx(INFINITE, true);
  }


  void HandleProgressCallback(const char *data, size_t size) {
    HandleScope scope;

    v8::Local<v8::Value> argv[] = {
        New<v8::Integer>(*reinterpret_cast<int*>(const_cast<char*>(data)))
    };
    progress->Call(1, argv);
  }

  private:
    Callback *progress;
    AsyncProgressWorker::ExecutionProgress *executionProgress;
};

NAN_METHOD(DoProgress) {
  Callback *progress = new Callback(info[0].As<v8::Function>());
  Callback *callback = new Callback(info[1].As<v8::Function>());
  AsyncQueueWorker(new KeyboardEventWorker(callback, progress));
}

NAN_MODULE_INIT(Init) {
  Set(target
    , New<v8::String>("init").ToLocalChecked()
    , New<v8::FunctionTemplate>(DoProgress)->GetFunction());
}

NODE_MODULE(asyncprogressworker, Init)

问题#1:为了能够将消息发送回node.js,我需要复制AsyncProgressWorker :: ExecutionProgress的指针并使其可用于整个类,因此当HookCallback触发时它可以发送消息给的node.js。

编译器不喜欢这个

  

.. \ binding.cc(21):错误C2440:'=':无法转换为'const   Nan :: AsyncProgressWorker :: ExecutionProgress *'to'Nan:   :AsyncProgressWorker :: ExecutionProgress *'   [C:\用户\ eksrow \ GDrive的\项目\ vscode \节点母语问候世界\建造\结合蛋白   g.vcxproj。

     

.. \ binding.cc(21):注意:转换失去限定符

格式化:

  

'const Nan :: AsyncProgressWorker :: ExecutionProgress *'

     

'Nan :: AsyncProgressWorker :: ExecutionProgress *'

这个我设法通过将关键字const添加到私有成员* executionProgress;来解决。但我不明白为什么会修复它,const变量一旦设置就不应该被改变。为什么这会编译?

问题#2:这个问题非常奇怪:

  

.. \ binding.cc(22):错误C3867:'KeyboardEventWorker :: HookCallback':   非标准语法;使用'&amp;'创建指针成员   [C:\用户\ eksrow \ GDrive的\项目\ vscode \节点天然问候世界\构建\ binding.vcxproj]

我在网上查了很多例子,他们都有相同的语法:

  1. SetWindowsHookEx #1
  2. SetWindowsHookEx #2
  3. 我无法看到我的代码与他们的代码之间的区别。

    如果我执行编译器所说的操作并在该行中添加&符号,则会产生完全不同的错误:

      

    .. \ binding.cc(22):错误C2276:'&amp;':对绑定成员的非法操作   函数表达式[C:\ Users \ eksrow \ gdrive \ proj   ECTS \ vscode \节点母语问候世界\建造\ binding.vcxproj]   .. \ binding.cc(22):错误C2660:'SetWindowsHookExA':函数没有   取3个参数[C:\ Users \ eksrow \ gdrive \ project   小号\ vscode \节点天然问候世界\构建\ binding.vcxproj]

1 个答案:

答案 0 :(得分:1)

对于问题#1 ,您正确地将const限定符标识为问题。

您在声明后可以分配给const成员变量的原因是const位于const AsyncProgressWorker::ExecutionProgress *executionProgress。这是一个指向常量AsyncProgressWorker :: ExecutionProgress的变量指针。这意味着您可以更改指针的值(例如,在上面的示例中重新分配它),但您无法更改它指向的数据。 The top answer of this question对这个概念有很好的解释。

问题#2 ,错误是由于尝试将类的成员函数作为函数回调传递而引起的。这根本不可能(嗯,没有解决方法......见下文) - 成员方法与函数不同,这是SetWindowsHookEx所期望的。您可以设置回调函数static,但之后将无法访问_hook成员。

Here is an external page针对此确切问题采用(非常黑客)的解决方法。它应该允许您以您当前尝试使用它的方式使用SetWindowsHookEx。但是,我建议重新考虑应用程序挂钩的方式,而不是看看是否有办法注册单个全局函数或静态成员函数作为应用程序的回调。

与您的问题无关:除非您在示例中省略了代码,否则您永远不会取消SetWindowsHookEx中设置的挂钩。看看MSDN for UnhookWindowsHookEx