Playing Around With js ctypes on Linux

I’m pretty elated about the ctypes module introduced in Firefox 3.6. ctypes.jsm is a module that lets chrome code call functions from shared libraries. This is a big win for a lot of extension developers. The baseline is that you no longer have to create an XPCOM component to call C++ code from javascript.

I had wanted to speed up some calculation-heavy js I was using in my extension by writing it in C++. Writing a C++ XPCOM component would be a painful process, so I decided to ditch the effort…then I found out about ctypes!

Ctypes can help with calling Win API functions and such, and there are some examples of this on the ctypes.jsm wiki page for this. My use case however was loading my own shared library, so I decided to put together a short end-to-end tutorial on how to call your own C code from your extension.

First we write a little C function and put it in add.c:

int add(int a, int b) {
  return a + b;
}

To get a shared library from this code, compile with these commands:

gcc -fPIC -c add.c
gcc -shared -o add.so add.o

Now you have a file called add.so, which we can load from ctypes. Say you put add.so in your addon’s content directory, then your javascript might look something like this:

Components.utils.import("resource://gre/modules/ctypes.jsm");

function add(a, b) {
  var file = getFile("chrome://myext/content/add.so");
  var lib = ctypes.open(file); 

  var addc = lib.declare("add",
                           ctypes.default_abi,
                           ctypes.int32_t, // return type
                           ctypes.int32_t, // arg1 type
                           ctypes.int32_t // arg2 type
  );
  return addc(a, b);
}


function getFile(chromeURL) {
  // convert the chrome URL into a file URL
  var cr = Components.classes['@mozilla.org/chrome/chrome-registry;1']
           .getService(Components.interfaces.nsIChromeRegistry);
  var io = Components.classes['@mozilla.org/network/io-service;1']
           .getService(Components.interfaces.nsIIOService);
  var uri = io.newURI(decodeURI(chromeURL), 'UTF-8', null);
  var fileURL = cr.convertChromeURL(uri);
  // get the nsILocalFile for the file
 return  fileURL.QueryInterface(Components.interfaces.nsIFileURL).file;
}

Now try calling your add function from js. The getFile function isn’t that pretty, hopefully in the future there will be a way to open a library from a chrome url. Also, you can’t use ctypes from Worker threads, so that is very sad.

4 thoughts on “Playing Around With js ctypes on Linux

  1. Hey this seems to be interesting thing, and i would like to implement the same.

    My scenario is to read registry using some inbuilt windows functions of client machine from java script on a webpage and place it in cookie.

    can this article help me out and if we are going to face any issues with this in future, please let me know.

    i want to develop my website with cross browser and cross platform compatibility.

    Thanks and Regards,
    Ganesh Majeti.

    P.S: please do rely me and thanks for this knowledge sharing. 🙂

  2. You can’t use this from your website, it’s for Firefox extensions only. It would be a big security problem if you could use this from a website.

Leave a reply to Savani Cancel reply