Mapping Java to C++ classes with JNI.
Hi everybody. At this I will explain how to map some C++ class to Java using JNI. This cover the differences between C and C++ in JNI usage and how to keep, in an Java object, a reference to a native object. I will try another aproach here where the explanation goes inside code as arguments. The roadmap used to compile and run this can be grasped from older posts.
Before start I want to add some motivation. I’ve been writting JNI interfaces for some time now. Some times the whole stack is being written only to export some functionality to Java guys. They think in object while I think as struct. This is the biggest problem here. C is all about procedural while Java is all about OOP. There are two possible aproaches:
- Using procedural design in C and OOP design in Java and doing the translation in JNI code.
- Using OOP design in C. Some may think (but C does not support OOP). Yes, it doesn’t, but we’re talking about design, not about language support. The Linux kernel has a lot of OO design inside it and written in C.
Usually when design a new interface I take the second option. If the interface already exists the first option may be simpler and I like simplicity. Also, sometimes you don’t own the interface so the first option is the only option.
But doing OO in C is annoying. If you’re thinking “What the f*ck he means with
OO in C?” I mean object->method(object, parms...)
pattern. Where object
is
some struct with one function pointer for each method
. In this pattern the
object itself is passed as first argument to each method. The JNI itself uses
this pattern where JNIEnv
is passed as every function as first parameter.
After some time dealing with this problem I though Why not using C++ do specify native API? Doing so would make the whole thing more straightforward, simple, cleaner, etc.. But how to do it?”. This post is the result of my research.
The aproach is rather simple. Once you have a C++ class you must declare its Java counterpart. To keep Java and C++ instance tied together a private long attribute is used to hold C++ instance address. That “pointer” is used at native code to fetch the C++ instance at memory before calling it’s methods. The remaining of the post is explained at code comments. Take a look:
Regards,