So, after humming and hawing until I was fresh out of hum and down to my last batch of haw, I figured the time was right to try and get js-ctypes working to start contributing more to Mozilla. I have a trunk Firefox debug build I update once a month or so and figured since I popped my build-your-own cherry about a year ago, with PyXPCOM enabled no less, I should be able to get js-ctypes going without too much crying.
Verdict: well that was easy. Check out the code from the svn repo into mozilla/extensions/, add it to extensions in .mozconfig like so:
ac_add_options --enable-extensions=default,spatialnavigation,python,js-ctypes
and Bob's your proverbial uncle. It built cleanly on my working Fx trunk build, and it was available to extensions and whatnot.Now, I use Linux (openSUSE 10.2 currently) and Mark Finkle wrote on his blog when announcing js-ctypes, "compiles on Linux, but I haven’t got around to testing it." It turns out it built cleanly, but it didn't work. Some quick testing using a hastily thrown together extension showed that
nsINativeTypes::Open()
failed — it didn't load shared libraries (libc.so.6 in this case). After hitting mxr it turned out a PRLibSpec
struct is initialized differently depending on the platform, and the code only covered the WIN32 case. That's bug #416119. The fix was easy enough, an #ifdef and a couple lines of code, but I'm still not sure the string PromiseFlatCString
call is redundant as NS_Convert...
returns an nsCAutoString
which is "flat" already).That took care of the first problem and js-ctypes now loaded shared libraries in Linux. Score one for the newb. The next step was to try and call some function. I chose
puts()
, which is a part of libc and simply outputs a string of characters to stdout. Easy enough, right? Well, no. Since it uses a char* buffer for the string, I chose nsINativeTypes.STRING
when declaring the function like so*:const nsINativeTypes = Ci.nsINativeTypes;Upon trying that code I was greeted with a segmentation fault. It turned out there was no implementation for the native type STRING in nsNativeMethod.cpp. Since there's no default catch-undefined-and-return-error in the switch blocks in
var library = Cc["@developer.mozilla.org/js-ctypes;1"]
.createInstance(Ci.nsINativeTypes);
library.open("libc.so.6");
var puts = library.declare("puts", /* function name */
nsINativeTypes.INT32, /* return type */
nsINativeTypes.SYSV, /* call ABI */
nsINativeTypes.STRING /* argument type */
);
var ret = puts("Hello World from js-ctypes!");
nsNativeMethod::Execute()
and declare()
doesn't care what type you specify (in reality any uint16 will work), when the function was called the call to ffi_prep_cif()
in nsNativeMethod::Execute()
had incomplete information about the parameters and exploded. Adding support for STRING is bug #416229. Thankfully, I could reuse the logic for WSTRING but use char* instead of PRUnichar* and fix the problem without any trouble.The customary money shot:

[*] Do note that the call ABI has to be specified. That bit me for about 30 minutes before I poked through the code thoroughly and realized the example code in Mark Finkle's original post didn't reflect that.
No comments:
Post a Comment