Jsctypes has been introduced in Firefox 3.6 with simple C function call and only simple types: int, char, string, … But the next iteration of jsctypes that is coming in Firefox 4 is going to allow full C binding, with support of C structures and the ability to define a javascript function and give it to C library as a function pointer.
No more compilation, no more mozilla sdk download, nor XPCOM stuff, just plain javascript and only a tiny part of function and datatype declaration before doing a native binding!
But let the code talk! Here is an example that display a tray icon on windows. You can copy and paste this code in your Javascript Console in Firefox 4 beta, just do not forget to change the icon path defined in the loadimage function call.
/* simply load "ctypes" object */
Components.utils.import("resource://gre/modules/ctypes.jsm");
/* Load libraries that we are going to use */
var libuser32 = ctypes.open("user32.dll");
var libshell32 = ctypes.open("shell32.dll");
/* Here is the tedious work of declaring functions arguments types and struct attributes types */
/* In fact it's quite easy, you just have to find which precise type are using your native functions/struct */
/* but it may be hard to known, for example in windows API, which precise type is behing their "HANDLE" type ... */
/* I recommend you to find and look at python ctype binding source code because they already had done this work */
/*
HANDLE WINAPI LoadImage(
__in_opt HINSTANCE hinst,
__in LPCTSTR lpszName,
__in UINT uType,
__in int cxDesired,
__in int cyDesired,
__in UINT fuLoad
);
*/
var loadimage = libuser32.declare("LoadImageA",
ctypes.stdcall_abi,
ctypes.int,
ctypes.int,
ctypes.char.ptr,
ctypes.int,
ctypes.int,
ctypes.int,
ctypes.int);
const LR_LOADFROMFILE = 16;
const IMAGE_ICON = 1;
var notificationdata = ctypes.StructType("NOTIFICATIONDATA",
[{ cbSize : ctypes.int },
{ hWnd : ctypes.int },
{ uID : ctypes.int },
{ uFlags : ctypes.int },
{ uCallbackMessage : ctypes.int },
{ hIcon : ctypes.int },
{ szTip : ctypes.char.array(64) },
{ dwState : ctypes.int },
{ dwStateMask : ctypes.int },
{ szInfo : ctypes.char.array(256) },
{ uTimeoutOrVersion : ctypes.int },
{ szInfoTitle : ctypes.char.array(64) },
{ dwInfoFlags : ctypes.int },
{ guidItem : ctypes.int },
{ hBalloonIcon : ctypes.int }
]);
const NIF_ICON = 0x00000002;
/*
BOOL Shell_NotifyIcon(
__in DWORD dwMessage,
__in PNOTIFYICONDATA lpdata
);
*/
var notifyicon = libshell32.declare("Shell_NotifyIcon",
ctypes.stdcall_abi,
ctypes.bool,
ctypes.int,
notificationdata.ptr);
const NIM_ADD = 0x00000000;
/* And now, the "real" code that is calling C functions */
/* load our ico file */
var hIcon = loadimage(0, "c:\\default.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
/* create a C struct that is defining a notification in tray */
var icon = notificationdata();
icon.cbSize = notificationdata.size;
icon.uFlags = NIF_ICON;
icon.szTip = "My Tray Icon";
icon.hIcon = hIcon;
/* Display this notification! */
notifyicon(NIM_ADD, icon.address());
We will be able to go futher and define a function callback to handle click
events on the trayicon, but there is currently a bug which cause some crashes
when using ctypes.FunctionType on windows. (ctypes.FunctionType allow to
transform a custom Javascript function to a C function pointer)
Here is related bugs, which are still in process:
- Bug 573066 - Fix ctypes stdcall closure tests
- Bug 585175 - Don’t automangle ctypes stdcall symbols for WINAPI
The first leads to crashes with FunctionType, and the second may lead to lib.declare with unfindable symbols errors when using ctypes.stdcall_abi.