At the heart of js-ctypes is the ctypes.open()
function. This must be called before any work can commence. There are two options:
- Custom Native File (DLL, SO, DYLIB, etc.)
- Standard OS Libraries
Custom native file
For this method, a native file must be created. A native file for use on UNIX systems is an SO file, which is created and a C function called add()
is written.
int add(int a, int b) { return a + b; }
To make this a shared library, a native file which can be loaded and used from js-ctypes, compile it with these commands:
gcc -fPIC -c myCFuntionsForUnix.c gcc -shared -o myCFuntionsForUnix.so myCFuntionsForUnix.o
A file named myCFuntionsForUnix.so
is successfully created. This native file can be placed in any folder of an addon and then loaded from js-ctypes. They can also be loaded from the system library path.
Loading the native file
If your addon is restartless, you must set it to be unpacked. See: http://stackoverflow.com/questions/19382201/how-to-load-dll-from-sdk-addon-data-folder
It is important to note that custom native files cannot be loaded through chrome://
or resource://
URIs. They must be accessed through a local file path (file://
) or a JAR path (jar:
). If the addon is an unpacked addon, such as bootstrap or Add-on SDK addons, the JAR path must be used. Therefore, the path has to be converted and then the converted path is used for loading with ctypes.open
.
If the native file is located at chrome://youraddon/content/mySubFolder/myCFunctionsForUnix.so
then it is converted to a File URI like this:
Components.utils.import("resource://gre/modules/Services.jsm"); var cr = Components.classes['@mozilla.org/chrome/chrome-registry;1'].getService(Components.interfaces.nsIChromeRegistry); var chromeURI_myLib = Services.io.newURI('chrome://youraddon/content/mySubFolder/myCFunctionsForUnix.so', 'UTF-8', null); var localFile_myLib = cr.convertChromeURL(chromeURI_myLib); var jarPath_myLib = localFile_myLib.spec; // "jar:file:///C:/Users/Vayeate/AppData/Roaming/Mozilla/Firefox/Profiles/aecgxse.Unnamed%20Profile%201/extensions/youraddon@jetpack.xpi!/mySubFolder/myCFunctionsForUnix.so" var filePath_myLib = localFilemyLib.path; // "file:///C:/Users/Vayeate/AppData/Roaming/Mozilla/Firefox/Profiles/aecgxse.Unnamed%20Profile%201/extensions/youraddon@jetpack.xpi!/mySubFolder/myCFunctionsForUnix.so"
If your add-on is a bootstrap add-on, then you don't need to use this method to convert a chrome:// path; instead, on startup procedure of the bootstrap add-on obtain the File and/or JAR path from installPath from the aData parameter.
function startup(aData, aReason) { var nsIFile_folder = aData.installPath; // if addon is unpacked, this will be the addon folder. if addon is packed, this will be addon xpi }
This can then be joined with your file name to obtain it's path like this:
function startup(aData, aReason) { var jarPath_folder = 'jar:' + OS.Path.toFileURI(aData.installPath.path) + '!/'; // if unpacked is false in install.rdf this will look like: "jar:file:///C:/Users/Vayeate/AppData/Roaming/Mozilla/Firefox/Profiles/aksozfjt.Unnamed%20Profile%2010/extensions/AsyncZip@jetpack!/" var filePath_folder = aData.installPath.path; // if unpacked is set to false in install.rdf this will look like: "C:\Users\Vayeate\AppData\Roaming\Mozilla\Firefox\Profiles\aksozfjt.Unnamed Profile 10\extensions\AsyncZip@jetpack" var filePath_myLib = OS.Path.join(filePath_folder, 'mySubFolder', 'myCFunctionsForUnix.so'); var jarPath_myLib = jarPath_folder + 'mySubFolder/myCFunctionsForUnix.so'; }
This can then be opened and the C functions within can be used from js-ctypes.
var myLib = ctypes.open(filePath_myLib); var add_with_c = lib.declare("add", ctypes.default_abi, ctypes.int, // return type ctypes.int, // a ctypes.int // b ); var rez = add_with_c(2, 5); // rez is 7 lib.close();
References
- Heather's Paragraphs: Playing Around with JS-Ctypes on Linux - Credits for basis of this article
- GitHub :: diegocr - fx-sapi-test - Creating a native file for Windows (DLL) and use in a simple bootstrap add-on