jnipp is a C++11 Java Native Interface wrapper supposed to make life easier.
- you need c++11 support:
-std=c++11 - compile with
-DJNIPP_USE_TYPE_TRAITSto use type traits if available; some versions of libstdc++ do not supporttype_traits: compile with-DJNIPP_USE_BOOSTand put boost in your include path. - some platforms (Android for example) do not completely support thread local storage. use
-DJNIPP_THREAD_LOCAL_PTHREADto fallback to pthread.
cd test
make -f Makefile.osx
make -f Makefile.linux
It does not work?
- recompile the generate script: cd generate; javac generate.java
- install clang
- fix include path in Makefile
#include <jnipp.h>
using namespace jnipp;
JNIEnv* jni_env_pointer = /* ... */;
Env::Scope scope(jni_env_pointer);
LocalRef<String> str = String::create("Some String!");
Method<String> String_toUpperCase("java/lang/String", "toUpperCase", "()Ljava/lang/String;");
LocalRef<String> str_upper = String_toUpperCase(str);
compile with:
clang -std=c++11 -lc++ -fvisibility=hidden -fvisibility-inlines-hidden -Wl,-dead_strip test.cpp -o test
use ./generate/generate java.lang.String to generate the java class header file
#include <jnipp.h>
#include "_java.h" // contains the JavaLangString definition
using namespace jnipp;
JNIEnv* jni_env_pointer = /* ... */;
Env::Scope scope(jni_env_pointer);
LocalRef<JavaLangString> str = String::create("Some String!");
LocalRef<JavaLangString> str_upper = str->toUpperCase();
Please note that due to the fact that some names are reserved in C++ and C++ also does not allow fields and methods with the same name, some method or member names are made unique by appending underscores (i.e. someField_ instead of someField)
This library is designed to generate as close to manually written code as possible.
- All functions are inlined
- No additional reference counters
- No allocations
- the "test" sample produces a .dylib of 30kb
When using java class headers you need to use dead code stripping, for clang:
clang source.cpp -fvisibility=hidden -fvisibility-inlines-hidden
clang source.o -Wl,-dead_strip
- clean up generate tool (own dir, .jar, output file name option etc.)
- option to limit scope of generate tool.
-
stores the current
JNIEnv*as a thread local variable -
use
Env::get()to get the currentJNIEnv* -
use
Env::peek()to get the currentJNIEnv*without throwing an exception if it is null -
use
Env::Scope myScope(my_jni_env)to set theJNIEnv*. The scope setter will restore the previous value on destruction. -
use
Env::Scope myScope(my_jni_vm)to attach the current thread to the VM. -
use
Env::hasException()to check if an exception has occured, Env::getException() to get the exception object. -
use
Env::throwException(exceptionObject)orEnv::throwException(exceptionClass, stringArgument)to throw an exception.
Refis an unmanaged reference (jobject). Use these for method arguments.Refs are not larger than ajobjectand do not need to be passed by reference.- all
Refs supportoperator ==(IsSameObject) andoperator boolchecking (for not null) - a
LocalRefkeeps a jni local reference and callDeleteLocalRefon destruction. Use these for returning objects. The copy constructor will callNewLocalRef. - use
LocalRef.steal()to get the jobject from a LocalRef and zeroing the LocalRef (i.e. preventing the call to DeleteLocalRef on destruction). - use
LocalRef::use(jobject)to use an existing local reference jobject. - a
GlobalRefis a java global reference (NewGlobalRef). on destruction, callsDeleteGlobalRef. - a
WeakRefis a java weak global reference (NewWeakGlobalRef). on destruction, callsDeleteWeakGlobalRef. These are not a subclass ofRefand can only be used to initialize aLocalRef(to make sure that the weak reference is not garbage collected during usage).
- for arguments of type
Ref<String>you can directly pass aconst char*instead of passingString::create(...) - for a
Ref<Array>you can directly use the array subscript operator, i.e.myArrayRef[0]instead of(*myArrayRef)[0] Ref<String>can be cast toconst char*andstd::stringRef<String>has aoperator ==(const char*)(and !=)
Method<returnType, argType1, argType2, argType3> method(const char* / Ref<Class> class, const char* methodName, const char* signature);defines a method.- Same for
StaticMethodandNonvirtualMethod - use
method.call([thisref, ]arg1, arg2, arg3);to call Field<type> field(const char* / Ref<Class> class, const char* fieldName, const char* signature);defines a field- Same for
StaticField - use
field.get([thisref])andfield.set([thisref, ]value) - there is also a cast and assignment operator
Constructor<classType, argType1, ...> constructor(const char* / Ref<Class> class, const char* signature);defines a constructor.- use
constructor.construct(arg1, arg2, ..)to call
Array<Object>is an object array. You can uselength(),get(index)andset(index, newValue). An[]operator exist, but only for reading.Array<Object>::construct(size, elementClass)creates a new array.- object arrays support iterators, so you can use
for (auto something in myObjectArray) Array<jbyte>(or any other primitive) is a primitive array. It also supportslength(),get(index)andset(index, newValue), but works by locking the buffer into memory on first usage (GetByteArrayElements). The subscript operators work for getting and setting, and the primitive array can also be cast to a pointer.- upon next usage as a
jobjectthe buffer is unlocked (ReleaseByteArrayElements) automatically. - you can use
lock()andunlock()to do this manually.
- The
generatetool will create a header file containing all method and field definitions. - Referenced classes are included.
- Pass all java classes you need to access as parameters (i.e.
./generate java.lang.String java.util.Map java.util.Set) - Output filename is always
_java.h - The generated classes are named
JavaLangStringforjava.lang.Stringand so on. - dont forget to turn on dead code stripping (see above), otherwise that will make your executable really large.