It seems most documentation or helper libraries relating to JNI (Java Native Interface) are concerned with calling native code from Java. This seems to be the main use of it, even though it is capable of more.
I want to mostly work in the opposite direction: modify an existing (fairly large) portable C++ program by adding some Java libraries to it. For example, I want to make it call databases via JDBC, or message queue systems via JMS, or send emails, or call my own Java classes, etc. But with raw JNI this is pretty unpleasant and error-prone.
So I would ideally like to write C++ code that can call Java classes as easily as C++/CLI can call CLR classes. Something like:
using namespace java::util::regex; // namespaces mapped
Pattern p = Pattern.compile("[,\\s]+");
array<:lang::string> result =
p.split("one,two, three four , five");
for (int i=0; i < result.length(); i++)
std::cout << result[i] << std::endl;
This way, I wouldn't have to manually do the work of getting the method ID by passing the name and the weird signature strings, and would be protected from programming errors caused by the unchecked APIs for calling methods. In fact it would look a lot like the equivalent Java.
NB. I AM STILL TALKING ABOUT USING JNI! As an underlying technology it is perfect for my needs. It is "in process" and highly efficient. I don't want to run Java in a separate process and make RPC calls to it. JNI itself is fine. I just want a pleasant interface to it.
There would have to be a code generation tool to make equivalent C++ classes, namespaces, methods, etc. to exactly match what is exposed by a set of Java classes I specify. The generated C++ classes would:
Have member functions that accept similarly-wrapped versions of their parameters and then do the necessary JNI voodoo to make the call.
Wrap the return values in the same way so I can chain calls in a natural way.
Maintain a per-class static cache of method IDs to avoid looking up them every time.
Be totally thread-safe, portable, open source.
Automatically check for exceptions after every method call and produce a std C++ exception.
Also work for when I'm writing native methods in the usual JNI way but I need to call on to other Java code.
The array should work totally consistently between primitive types and classes.
Will no doubt need something like global to wrap references in when they need to survive outside of a local reference frame - again, should work the same for all array/object references.
Does such a free, open-source, portable library/tool exist or am I dreaming?
Note: I found this existing question but the OP in that case wasn't nearly as demanding of perfection as I am being...
Update: a comment about SWIG led me to this previous question, which seems to indicate that it is mostly about the opposite direction and so wouldn't do what I want.
IMPORTANT
This is about being able to write C++ code that manipulates Java classes and objects, not the other way round (see the title!)
I already know that JNI exists (see the question!) But hand-written code to the JNI APIs is unnecessarily verbose, repetitious, error-prone, not type-checked at compile time, etc. If you want to cache method IDs and class objects it's even more verbose. I want to automatically generate C++ wrapper classes that take care of all that for me.
Update: I've started working on my own solution:
If this already exists, please let me know!
NB. If you're considering using this in your own project, feel free, but bear in mind that right now the code is a few hours old, and I only wrote three very unstrenuous tests so far.
解决方案
Yes, there are existing tools that do exactly this -- generate C++ wrappers for Java classes. This makes use of Java APIs in C++ more transparent and enjoyable, with lower cost and risk.
The one that I've used the most is JunC++ion. It's mature, powerful and stable. The primary author is very nice, and very responsive. Unfortunately, it's a commercial product, and pricey.
Jace is a free, open-source tool with a BSD license. It's been years since I last played with jace. Looks like there's still some active development. (I still remember the USENET post by the original author, over a decade ago, asking basically the same question you're asking.)
If you need to support callbacks from Java to C++, it's helpful to define C++ classes that implement Java interfaces. At least JunC++ion allows you to pass such C++ classes to Java methods that take callbacks. The last time I tried jace, it did not support this -- but that was seven years ago.