Boost logo

Boost :

Subject: [boost] Library proposal: Boost.JniTools - The easy way to call Java methods from C++ (build on top of JNI)
From: Boris Brodski (brodsky_boris_at_[hidden])
Date: 2011-02-09 05:22:57


Hello everyone,

I'm the maintainer of the 7-Zip-JBinding project:
- On SourceForge: http://sevenzipjbind.sourceforge.net/
- On GitHub: https://github.com/borisbrodski/sevenzipjbinding/tree/RW (Check
the RW branch)

In order to call C++ code from Java and vice versa the JNI (Java Native
Interface)
should be used. This interface is low level and provides little safety. (Java VM
crashes very easy)
Also to get a good performance, a bunch of code is always needed to cache ids
and some pointers
returned from jni.

In the new version of 7-Zip-JBinding (see git RW branch) I wrote a library, that
solves some of JNI problems. It uses simple DSL (defines) to describe java
classes/interfaces
with their methods/fields. It generates from the DSL during pre-compile time
some kind of
easy to use skeletons around Java classes and interfaces, providing very simple
access
to their methods and fields.

Here are the features:
- Type-safe calls from C++ to Java - The compiler will check the number and type
of
  all passed arguments to the called methods. The same applies to setting field.
- Caching of method ids and class pointers.
- Auto-determining java method signature from the DSL.
- Consistent JNI low level error handling
- Tools to debug checking and cleaning exceptions after each method call.
- Code completion of the java methods and fields from C++ with IDE,
  capable of expanding defines (for example, with Eclipse CDT).

Here is a very simple example, how this library can be used:

--- JAVA
package test;
class MyClass {
    public long doSomething(boolean param1, int param2, long param3) { ... }
}

--- C++ (The classic usage of the JNI)
jlong callDoSomething(JNIEnv * env, jobject instance, jboolean param1, jint
param2, jlong param3)
{
    c = env->FindClass("test/MyClass");
    if (!c) { ... handle_error ... }

    // Writing signatures is annoying
    jmethodID mid = env->GetMethodID(c, "doSomething", "(ZI)J"); // MethodId
should be cached here
    if (!mid) { ... handle_error ... }

    // Wrong parameter type/count here cause VM to crash
    jlong result = env->CallLongMethod(instance, mid, param1, param2, param3);

    if (env->ExceptionOccurred()) { ... handle_exception ... }
    env->ExceptionClear(); // Failing to call this method cause VM to crash ONLY
IN CASE of exception

    return result;
}

--- C++ (Using JniTools)

// Describe class. (This could be also generated directly from Java class)

JT_BEGIN_CLASS("test", MyClass)
    JT_CLASS_VIRTUAL_METHOD(Long, doSomething, JT_BOOLEAN(param1, JT_INT(param2,
JT_LONG(param3, _))))
JT_END_CLASS

jlong callDoSomething(JNIEnv * env, jobject instance, jboolean param1, jint
param2, jlong param3)
{
    // with Eclipse CDT:
    // - the class and method can be auto-completed.
    // - the parameters can be viewed with the real names (from DSL)
    // - the return type can be viewed
    // - "Jump to definition" jumps to the corresponding DSL
    jlong result = jni::InArchiveImpl::doSomething(env, instance, param1,
param2, param3);

    if (env->ExceptionOccurred()) { ... handle_exception ... }
    
    // Failing to call this method cause VM to crash ALWAYS in debug mode
    // Controlled by define:
    // JNI_TOOLS_DEBUG_CALL_AND_EXCEPTION_CLEAR_BEHAVIOR
    jni::expectExceptionCheck(env);

    return result;
}

The JniTools library is currently not fully stand-alone. There are some
dependencies to other .h files from the 7-Zip-JBinding.
Also JniTools doesn't cover all the jni features, that can be covered.
The test-coverage of the existing features is however good.

Here a some direct links:
- The JniTools library:
https://github.com/borisbrodski/sevenzipjbinding/blob/RW/jbinding-cpp/JavaStaticInfo.h
 (has to be renamed)
- The usage example:
https://github.com/borisbrodski/sevenzipjbinding/blob/RW/jbinding-cpp/JavaStatInfos/JavaPackageSevenZip.h

Tests (called from JUnit):
- C++:
https://github.com/borisbrodski/sevenzipjbinding/blob/RW/test/CTests/JniToolsTest.cpp

- Java:
https://github.com/borisbrodski/sevenzipjbinding/tree/RW/test/JavaTests/src/net/sf/sevenzipjbinding/junit/jnitools

In case, this library has a real chance to become a part of the Boost library,
I would be happy to remove all the7-Zip-JBinding dependencies,
implement missing features and discuss other possible improvements.
It would be match better, if someone will volunteer to help me on this and
share the responsibility.

Regards,
Boris Brodski

 
____________________________________________________________________________________
Bored stiff? Loosen up...
Download and play hundreds of games for free on Yahoo! Games.
http://games.yahoo.com/games/front


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk