JSctypes round two

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:

The first leads to crashes with FunctionType, and the second may lead to lib.declare with unfindable symbols errors when using ctypes.stdcall_abi.