2

我有一个小的引导扩展,它加载一个 dll 文件startup()并将其保存在一个全局变量中。我不知道如何正确使用它,也许你会纠正我,但我更想知道我从 dll 文件中使用的函数是否可以异步调用。

现在我正在做的是:

Components.utils.import("resource://gre/modules/ctypes.jsm");
log = function(str) { Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(str+'\n'); }

var lib;
var someFunc;

...

function startup(aData, aReason) {
   lib = ctypes.open(dllPath);
   if(!lib)
   {
      log("dll load error");
      lib = null;
      return;
   }
   else
   {
      var initDll = lib.declare("Init", ctypes.default_abi, ctypes.long);
      var status = initDll();
      log("Dll returned " + status);

      if(status == ctypes.long(0))
      {
         someFunc = lib.declare("SomeFunc", ctypes.default_abi, ctypes.long, ctypes.long);
      }
   }
}

一旦我有someFunc我经常在代码中使用它,但调用需要很长时间。有没有办法异步调用它?或者以 Firefox 在通话期间不会冻结的方式调用它?

4

2 回答 2

3

如果外部(通过绑定ctypes)API 本身不是异步的,根据定义,您将无法在 JavaScript 中异步调用它。

最简单的解决方法是使用某种 WebWorker 在后台线程中调用 API。鉴于您需要做一些特权工作,ChromeWorker API 符合要求。

它的机制是:

  1. 启动ChromeWorker(又名“工人”)
  2. 通过向“工人”发送消息postMessage以启动“工作”
  3. 'worker' 中的消息事件处理程序应该加载ctypes并对外部代码进行同步调用,然后......
  4. 让“工人”通过postMessage向呼叫者(您的主代码)发送消息说(实际上,“我完成了”)。

如果外部 API 需要特定于调用的参数,您可以组织通过第一个postMessage. 如果外部 API 返回任何重要的内容,您可以通过第二个postMessage.

所有这些看起来都有些繁琐,因此您需要将其打包到JavaScript 代码模块中;这将允许您将这些ctypes内容与其余代码分开,并且您可以在调用线程(模块内部)中使用createEventanddispatchEvent使 API 看起来是异步的,但隐藏“worker”部分。

于 2014-06-02T01:12:43.160 回答
0

这里展示了如何通过 jsctypes 使用不同的函数。它可能不适用于您上面的内容,如果这对您没有帮助,请告诉我,我会看看您的具体情况。

const {Cc, Ci, Cu} = require('chrome');
Cu.import("resource://gre/modules/ctypes.jsm");

/*start getcursorpos*/
var lib = ctypes.open("user32.dll");

/*foreground window stuff*/
var FindWindowA = lib.declare('FindWindowA', ctypes.winapi_abi, ctypes.uint32_t, ctypes.jschar.ptr, ctypes.jschar.ptr)
var GetForegroundWindow = lib.declare('GetForegroundWindow', ctypes.winapi_abi, ctypes.uint32_t)
function doFindWindow() {
    var wm = Cc['@mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator);
    var title = wm.getMostRecentWindow('navigator:browser').gBrowser.contentDocument.title;
    Cu.reportError('title=' + title)
    var ret = FindWindowA('', title + ' - Mozilla Firefox');
    //var ret = GetForegroundWindow();

    Cu.reportError(ret);
}
/*end foreground window stuff*/

/* Declare the signature of the function we are going to call */
const struct_lpPoint = new ctypes.StructType("lpPoint",
                        [ { "x": ctypes.int },
                          { "y": ctypes.int } ]);
var GetCursorPos = lib.declare('GetCursorPos', ctypes.winapi_abi, ctypes.bool, struct_lpPoint.ptr);

function doGetCursorPos() {
        var point = new struct_lpPoint;
        var ret = GetCursorPos(point.address());
        Cu.reportError(ret);
        Cu.reportError(point);
}
/*end getcursorpos*/




/*start setcursorpos*/
//var lib = ctypes.open("user32.dll"); //already called on line 4
var SetCursorPos = lib.declare('SetCursorPos', ctypes.winapi_abi, ctypes.bool, ctypes.int, ctypes.int)

function doSetCursorPos() {
    var ret = SetCursorPos(10, 10);
}
/*end setcursorpos*/

/*start mouse_event*/
//used to click
//const DWORD = ctypes.uint32_t; //this just shows you that DWORD == ctypes.uint32_t
var mouse_event = lib.declare('mouse_event', ctypes.winapi_abi, ctypes.void_t, ctypes.uint32_t, ctypes.uint32_t, ctypes.uint32_t, ctypes.uint32_t, ctypes.uintptr_t);
const MOUSEEVENTF_LEFTDOWN = 2;
const MOUSEEVENTF_LEFTUP = 4;

function domouse_event() {
    var ret = mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
    var ret = mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}
/*end mouse_event*/


/*start MessageBoxW*/
//var lib = ctypes.open("user32.dll"); //already called on line 4
var MessageBoxW = lib.declare('MessageBoxW', ctypes.winapi_abi, ctypes.int32_t, ctypes.int32_t, ctypes.jschar.ptr, ctypes.jschar.ptr, ctypes.int32_t);
var MB_OK = 0;

function doMessageBoxW() {
    var ret = MessageBoxW(0, "Hello world", "title", MB_OK);
}

/*end MessageBoxW*/

exports.main = function (options, callbacks) {



};


exports.onUnload = function (reason) {
    lib.close();
}

var { Hotkey } = require("hotkeys");

var showHotKey = Hotkey({
    combo: "alt-w",
    onPress: function() {
        /*setcursor stuff*/
        //doSetCursorPos();
        //domouse_event();
        /*setcursor stuff*/

        /*foreground stuff*/
        doFindWindow();
        /*foreground stuff*/
    }
});

我发现关于stackoverflow的其他jsctype主题很有用:* Javascript String to C++ char pointer -JSCTypes中的LPSTR缓冲区 * FF插件:如何在javascript中声明C函数fgets

于 2014-05-05T06:28:11.647 回答