Is the following usable with JNI?
public NativeClass {
static {
System.loadLibrary("dll");
}
public static native void addListener(Listener listener);
}
public interface Listener {
public void eventOccurred(Info info);
}
public Info {
private final String s1;
private final String s2;
public Info(String s1, String s2);
// ... getters for use in Java
}
Is it possible to
- register a
Listener
object on a dll (should be no problem, as far as I found out)
- instantiate an
Info
object in the c/c++ code and use it as a parameter for calling Listener.eventOccured(Info...)
?
Or what would be a good way to implement a listener which gets some information from a DLL?
In my case - we have a dll wich does some work. We call this dll from java. Now we want to attach a listener to the dll, to push us some progress information while working. The above example is the listener part, which I don't know if it is possible regarding the constructor call to a Java constructor from c/c++.
A hint where to find a piece of documentation, which describes the answer would be nice - I could not find infos, which answered my question.
A small snippet of code, describing the c/c++ part would be the icing on the cake :)
The short answer is yes, you can hold, instantiate, and pass Java objects in a native layer via JNI.
In the jni documentation, you will find functions that will do this for you.
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html
You will also Use javap -s
and javah
to assist in finding your java method signatures for use in jni and to make your jni headers. See http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javap.html & http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javah.html
Here is a sample of what you will be doing. I haven't tested it, so just use it as a reference for writing your own. Note: be aware of package notations(I've assumed no package) & Exceptions. Exceptions can happen on any JNI call(env->...
), so check the documentation on how to deal with exceptions(ExceptionCheck
, ExceptionDescribe
, ExceptionClear
).
JavaVM * savedVM = NULL;
JNIEXPORT void JNICALL Java_NativeClass_addListener(JNIEnv *env, jobject obj_instance, jobject listener_instance)
{
env->GetJavaVM( &savedVM );
//save listener_instance for use later
saved_listener_instance = listener_instance;
}
void doSomething()
{
//Get current thread JNIEnv
JNIEnv * ENV;
int stat = savedVM->GetEnv((void **)&ENV, JNI_VERSION_1_6);
if (stat == JNI_EDETACHED) //We are on a different thread, attach
savedVM->AttachCurrentThread((void **) &ENV, NULL);
if( ENV == NULL )
return; //Cant attach to java, bail
//Get the Listener class reference
jclass listenerClassRef = ENV->GetObjectClass( saved_listener_instance );
//Use Listener class reference to load the eventOccurred method
jmethodID listenerEventOccured = ENV->GetMethodID( listenerClassRef, "eventOccurred", "(LInfo;)V" );
//Get Info class reference
jclass infoClsRef = ENV->FindClass( "Info" );
//Create Info class
jobject info_instance = ENV->NewObject( infoClsRef, ..... );//For you to fill in with your arguments
//invoke listener eventOccurred
ENV->CallVoidMethod( saved_listener_instance, listenerEventOccured, info_instance );
//Cleanup
ENV->DeleteLocalRef( info_instance );
}