Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/461.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用节点插件api将C库回调传递给NodeJS EventEmitter_Javascript_C++_Node.js_Hid_Node Addon Api - Fatal编程技术网

Javascript 使用节点插件api将C库回调传递给NodeJS EventEmitter

Javascript 使用节点插件api将C库回调传递给NodeJS EventEmitter,javascript,c++,node.js,hid,node-addon-api,Javascript,C++,Node.js,Hid,Node Addon Api,我目前正在编写一个节点模块,该模块使用 在大多数情况下,这是一项相当简单的任务。 唯一有问题的是Gamepad库的回调函数 我的想法是通过(…)使模块成为EventEmitter,通过.on公开这些回调。它已经以类似的方式在中完成 问题是,无论何时从本机模块触发事件,都会出现以下错误: internal/timers.js:531 timer._onTimeout(); ^ TypeError: Cannot read property '_

我目前正在编写一个节点模块,该模块使用

在大多数情况下,这是一项相当简单的任务。 唯一有问题的是Gamepad库的回调函数

我的想法是通过(…)使模块成为EventEmitter,通过
.on公开这些回调。它已经以类似的方式在中完成

问题是,无论何时从本机模块触发事件,都会出现以下错误:

internal/timers.js:531
          timer._onTimeout();
                ^

TypeError: Cannot read property '_events' of undefined
    at emit (events.js:163:23)
    at listOnTimeout (internal/timers.js:531:17)
    at processTimers (internal/timers.js:475:7)
my
binding.cc的重要部分:

#include <napi.h>
#include "gamepad/Gamepad.h" // The Gamepad library written by Alex Diner

// The JS .emit(event, ...args) function from the EventEmitter
Napi::FunctionReference emitFn;

void GamepadSetEmitFn(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();

    if (info.Length() < 1) {
        Napi::TypeError::New(env, "Parameter 'emitFn' needs to be defined.")
            .ThrowAsJavaScriptException();
        return;
    }

    if (!info[0].IsFunction()) {
        Napi::TypeError::New(env, "Parameter 'emitFn' needs to be a function.")
            .ThrowAsJavaScriptException();
        return;
    }
    // Sets the emitFn to the specified function
    emitFn = Napi::Persistent(info[0].As<Napi::Function>());
}

// The following handle functions are the callbacks for the actual Gamepad module

void HandleDeviceAttach(struct Gamepad_device* device, void* context) {
    if (emitFn == nullptr) return;

    Napi::Env env = emitFn.Env();
    Napi::String eventName = Napi::String::New(env, "attach");
    Napi::Number nDeviceID = Napi::Number::New(env, device->deviceID);
    emitFn.Call({ eventName, nDeviceID });
}

void HandleDeviceRemove(struct Gamepad_device* device, void* context) {
    if (emitFn == nullptr) return;

    Napi::Env env = emitFn.Env();
    Napi::String eventName = Napi::String::New(env, "remove");
    Napi::Number nDeviceID = Napi::Number::New(env, device->deviceID);
    emitFn.Call({ eventName, nDeviceID });
}

void HandleButtonDown(struct Gamepad_device* device, unsigned int buttonID, double timestamp, void* context) {
    if (emitFn == nullptr) return;

    Napi::Env env = emitFn.Env();
    Napi::String eventName = Napi::String::New(env, "down");
    Napi::Number nDeviceID = Napi::Number::New(env, device->deviceID);
    Napi::Number nButtonID = Napi::Number::New(env, buttonID);
    Napi::Number nTimestamp = Napi::Number::New(env, timestamp);
    emitFn.Call({ eventName, nDeviceID, nButtonID, nTimestamp });
}

void HandleButtonUp(struct Gamepad_device* device, unsigned int buttonID, double timestamp, void* context) {
    if (emitFn == nullptr) return;

    Napi::Env env = emitFn.Env();
    Napi::String eventName = Napi::String::New(env, "up");
    Napi::Number nDeviceID = Napi::Number::New(env, device->deviceID);
    Napi::Number nButtonID = Napi::Number::New(env, buttonID);
    Napi::Number nTimestamp = Napi::Number::New(env, timestamp);
    emitFn.Call({ eventName, nDeviceID, nButtonID, nTimestamp });
}

void HandleAxisMovement(struct Gamepad_device* device, unsigned int axisID, float value, float lastValue, double timestamp, void* context) {
    if (emitFn == nullptr) return;

    Napi::Env env = emitFn.Env();
    Napi::String eventName = Napi::String::New(env, "move");
    Napi::Number nDeviceID = Napi::Number::New(env, device->deviceID);
    Napi::Number nAxisID = Napi::Number::New(env, axisID);
    Napi::Number nValue = Napi::Number::New(env, value);
    Napi::Number nLastValue = Napi::Number::New(env, lastValue);
    Napi::Number nTimestamp = Napi::Number::New(env, timestamp);
    emitFn.Call({ eventName, nDeviceID, nAxisID, nValue, nLastValue, nTimestamp });
}

Napi::Object InitAll(Napi::Env env, Napi::Object exports) {

    // Applies the specified callback functions above to the respective Gamepad function.
    Gamepad_deviceAttachFunc(HandleDeviceAttach, NULL);
    Gamepad_deviceRemoveFunc(HandleDeviceRemove, NULL);
    Gamepad_buttonDownFunc(HandleButtonDown, NULL);
    Gamepad_buttonUpFunc(HandleButtonUp, NULL);
    Gamepad_axisMoveFunc(HandleAxisMovement, NULL);

    // All functionality exposed to JS
    // (including the function implementations omitted from this stackoverflow excerpt)
    exports.Set(Napi::String::New(env, "init"), Napi::Function::New(env, GamepadInit));
    exports.Set(Napi::String::New(env, "shutdown"), Napi::Function::New(env, GamepadShutdown));
    exports.Set(Napi::String::New(env, "detectDevices"), Napi::Function::New(env, GamepadDetectDevices));
    exports.Set(Napi::String::New(env, "processEvents"), Napi::Function::New(env, GamepadProcessEvents));
    exports.Set(Napi::String::New(env, "numDevices"), Napi::Function::New(env, GamepadNumDevices));
    exports.Set(Napi::String::New(env, "deviceAtIndex"), Napi::Function::New(env, GamepadDeviceAtIndex));
    exports.Set(Napi::String::New(env, "setEmitFn"), Napi::Function::New(env, GamepadSetEmitFn));

    return exports;
}
如果需要更多信息,请毫不犹豫地询问


提前感谢!:)

好吧,我自己解决了这个问题。我不知道为什么这是个问题,但是错误是因为我直接从C++事件的EnvikEdter类调用E.EIT(事件,…ARGS)方法。 我只是从JavaScript向我的模块添加了一个包装函数,现在它就像一个符咒:

const gamepad = require('../build/Release/gamepad.node')
const { EventEmitter } = require('events')

// Makes the native module extend 'EventEmitter'
gamepad.__proto__ = EventEmitter.prototype

// Wraps the emit function for the call from the native module
gamepad.applyEmit = (...args) => { 
    const event = args.shift()
    gamepad.emit(event, ...args)
}

// Exposes the applyEmit function to the native module
gamepad.setEmitFn(gamepad.applyEmit)

module.exports = gamepad
const gamepad = require('../build/Release/gamepad.node')
const { EventEmitter } = require('events')

// Makes the native module extend 'EventEmitter'
gamepad.__proto__ = EventEmitter.prototype

// Wraps the emit function for the call from the native module
gamepad.applyEmit = (...args) => { 
    const event = args.shift()
    gamepad.emit(event, ...args)
}

// Exposes the applyEmit function to the native module
gamepad.setEmitFn(gamepad.applyEmit)

module.exports = gamepad