Wrapping Rust for use in Java

So this post will be about wrapping a Rust library in Java. I wanted to use ncollide, a Rust collision detection library, in a Clojure project. I found ncollide attractive due to its simple, modern API design and good documentation. I was less interested in what was already available for the JVM. So why not try to wrap Rust… it would be a nice challenge!

Furthermore, I had a kind of strange childish admiration for people who wrap unmanaged code for a managed environment. I used SlimDX, a .NET wrapper over DirectX9, way back when it came out in 2007. The C++/CLI used to construct it seemed to me then like alchemy (partly because straight C++ also seemed like alchemy!) and I wanted that power. It has since been demystified for me, just by learning C properly and actually doing stuff with unmanaged code.

So using JNI was an important step for me. Actually, wrangling native code into a GCed, JITted, Runtimed world is great fun. No doubt. It also makes you think about the essentials. You’re forced to distill a piece of code into its core elements that can be boxed up and transported. Evrything else is noise. Actually, it should be simpler than that because in theory, given a language divide between interface and implementation, one should be able just to grab the interface (the headers) and create native method stubs in Java plus native JNI methods that wrap the original API methods. But you still have a lot of choice – how much do you do in the Java wrapper classes, or indeed do you even have a one to one relationship with the target classes at all? Why not have a big Java class with static methods? It’s design decisions like this that make the difference between – say – LWJGL and JOGL.

With Rust, ‘classes’ are structs with impl behaviours mixed and matched to them. There is therefore no tight coupling of data and method as in traditional OOP (I’d be interested if someone would care to explain to me in the comments how the in memory data layout of Rust structs + impl differs from C++ classes, and what you ‘get’ with a pointer to struct vs. what you ‘get’ with a pointer to a C++ class – you can see I’m new to Rust). Unlike with C++ JNI, then, where the object hierarchy of the native classes can be preserved, the lack of similarity between Java and Rust means that we may have to bake in the impl functionality into the Java classes.

The library I’m wrapping, ncollide, uses generics extensively. Java also has (compile time) generics. I’m not really sure how to create a generic bridge between the two. JNI is really about low level interoperability. There is a brute force way, which is: manually examine the type and dispatch native methods hardcoded for each one. There is no runtime type information on the JVM though, so all you’ll get is Object.

To be continued…