2016-04-18 5 views
0

現在、dllをNodeJSに統合しようとしています。 dllは、バス上に新しいメッセージを受信したときにコールバックをトリガするメッセージバスです(登録されている場合)。 添付されたdllはこの動作をシミュレートします。ループを無限ループで実行し、各ループでコールバックでCメソッドを呼び出します。 ここに私のテストケースである:NodeJS <--> 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モジュールで本当に可能ですか? エッジモジュールを代わりに使用するか、またはアドオンを使用する必要がありますか?

答えて

1

SetTimerは、Windowsの機能です。

それは、Windowsのメッセージループ持つ必要がありアプリケーションに機能するために:あなたの代わりに、処理の TimerProcを使用する場合でも、

あなたが呼び出し元のスレッドにメッセージをディスパッチする必要があるが、WM_TIMER

しかし、 node.jsはWindows上でIOCPを使用します。メッセージをディスパッチしません。

これを処理する1つの方法は、C++コードでuv_timerを使用することですが、これはnode-gypを使用してDLLをnode.exeにリンクする必要があります(libuv関数を共有ライブラリとしてエクスポートします)。

このソリューションはクロスプラットフォームであることに注意してください。

しかし、setIntervalを使用して既に実装している他の方法は、クロスプラットフォームでも簡単です。

setIntervalは、フードの下でuv_timerを使用します。

もう1つの解決策は、ネイティブライブラリに別のスレッドを作成し、そこからコールバック関数を呼び出すことです。 SetTimerを使用する予定の場合は、作成したスレッドで呼び出す必要があります。そこでWindowsメッセージループが必要になります。

関連する問題