我有一个小的引导扩展,在startup()
加载一个dll文件,并将其保存在一个全局变量中。我不知道如何正确使用这个也许你会纠正我,但我更感兴趣的是知道我从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在调用期间不会冻结?
如果外部(通过ctypes
绑定)API本身不是异步的,根据定义,您将无法在JavaScript中异步调用它。
最简单的解决方法是使用某种WebWorker在后台线程中调用API。看到你需要做一些特权的东西,ChromeWorker api符合要求。
它的机制是:
- 启动
ChromeWorker
(即'worker') - 通过
postMessage
向'worker'发送消息以启动'job' - worker中的消息事件处理程序应该加载
ctypes
并对外部代码进行同步调用,然后… - 让'worker'通过
postMessage
发送消息给调用者(你的主代码)说(有效地,"我完成了")。
如果外部API需要特定于调用的参数,您可以通过第一个postMessage
组织发布这些参数。如果外部API返回任何重要的东西,您可以组织通过第二个postMessage
接收这些。
所有这些看起来有点繁琐,所以你需要将其打包到JavaScript代码模块中;这将允许你把ctypes
的东西从你的代码的其余部分分开,你可以使用createEvent
和dispatchEvent
在调用线程(在模块内),使API看起来是异步的,但隐藏'worker'的部分。
这里展示了如何对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字符串到c++ char指针-LPSTR缓冲区在JSCTypes如何在javascript中声明C函数fgets