我们目前正在尝试将dll与NodeJS集成起来。dll是一条消息总线,在接收到总线上的新消息时触发回调(如果注册的话)。附加的dll模拟这种行为:循环无限,在每个循环上使用回调调用C方法。下面是我的测试用例:
var ref = require("ref");
var ffi = require('ffi');
var events = require('events');
var util = require('util');
var voidPtr = ref.types.void;
// Expose the DLL to node JS
var apiLib = ffi.Library('../bin/dispatch', {
// C method declaring the callback
'dispatchRegisterCallback': [ 'int', ['pointer', 'int'] ],
// C method which simply call dispatchRegisterCallback
'dispatchCallCallback': [ 'int', []]
});
// Callback
var myCallbackPtr = ffi.Callback('void', ['string'], function (message) {
console.log('callback: ' + message);
});
// Registering the callback on the C method, starts a loop and
// call the method that triggers the callback from the Dll each 1 second
// DOES NOT WORK
apiLib.dispatchRegisterCallback(myCallbackPtr, 1000);
// Make Node Loop
setInterval(function() {
console.log("loop");
// Triggering the callback from NodeJS : OK
//apiLib.dispatchCallCallback();
}
, 100);
// Keep the callback pointer to avoid GC
process.on('exit', function() {
myCallbackPtr
})下面是示例dll的源代码
#include "stdafx.h"
#include "dispatch.h"
#include <iostream>
pfnCallback * g_pfnCallback = NULL;
void CALLBACK timerFn(HWND hwnd, UINT uMsg, UINT timerId, DWORD dwTime)
{
std::cout << "dispatch.dll, timerFn" << std::endl;
if (g_pfnCallback != NULL)
{
std::cout << "dispatch.dll, timerFn : calling callback " << g_pfnCallback << std::endl;
g_pfnCallback("callback call (timer)");
}
}
/**
* Register a callback.
*/
int __stdcall dispatchRegisterCallback(pfnCallback fn, int interval)
{
std::cout << "dispatch.dll, dispatchRegisterCallback" << std::endl;
g_pfnCallback = fn;
SetTimer(NULL, 0, interval, (TIMERPROC)timerFn);
return true;
}
int __stdcall dispatchCallCallback()
{
std::cout << "dispatch.dll, dispatchCallCallback" << std::endl;
if (g_pfnCallback != NULL)
{
std::cout << "dispatch.dll, dispatchCallCallback : calling callback " << g_pfnCallback << std::endl;
g_pfnCallback("callback call by dispatchCallCallback");
return true;
}
return false;
}FFI模块真的有可能吗?我是应该使用边缘模块,还是应该使用加载项?
发布于 2016-08-29 01:01:30
SetTimer是一个Windows函数。
要使其工作,应用程序必须有一个Windows消息循环:
即使在使用TimerProc而不是处理WM_TIMER时,也需要在调用线程中分派消息。
但是node.js在Windows上使用IOCP。它不发送消息。
处理这一问题的一种方法是在计时代码中使用C++,但为此,必须使用节点-回转将dll链接到node.exe (它像共享库一样导出libuv函数)。
请注意,此解决方案是跨平台的。
但是,已经使用setInterval实现的另一种方法更容易,也更跨平台。
setInterval在引擎盖下使用uv_timer。
另一种解决方案是在本机库中创建另一个线程并从其中调用回调函数。如果您计划使用SetTimer,那么必须在创建的线程中调用它,您将需要一个Windows循环。
https://stackoverflow.com/questions/36694554
复制相似问题