JNI - Слушатель в C++/Java - возможно ли создавать экземпляры объектов Java в C++ и использовать их в качестве параметров

Можно ли использовать следующее с 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
}

Это возможно

  • зарегистрировать Listener объект на dll (не должно быть проблем, насколько я узнал)
  • создавать экземпляр Info объект в коде c/ C++ и использовать его в качестве параметра для вызова Listener.eventOccured(Info...)?

Или какой хороший способ реализовать слушателя, который получает некоторую информацию из DLL?

В моем случае - у нас есть dll, которая делает какую-то работу. Мы называем это DLL из Java. Теперь мы хотим подключить слушателя к dll, чтобы он давал нам информацию о прогрессе во время работы. Приведенный выше пример - это часть слушателя, которую я не знаю, возможно ли это в связи с вызовом конструктора для конструктора Java из c/ C++.

Подсказка, где найти часть документации, которая описывает ответ, была бы хороша - я не мог найти информацию, которая ответила на мой вопрос.

Небольшой фрагмент кода, описывающий часть c/ C++, был бы обледенением на торте:)

1 ответ

Решение

Короткий ответ - да, вы можете хранить, создавать и передавать объекты Java на собственном уровне через JNI.

В документации jni вы найдете функции, которые сделают это за вас. http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html

Вы также будете использовать javap -s а также javah помочь найти ваши сигнатуры java-метода для использования в jni и сделать ваши jni-заголовки. См. http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javap.html & http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javah.html

Вот пример того, что вы будете делать. Я не проверял это, так что просто используйте его как справочник для написания своего. Примечание: помните о нотациях пакетов (я не предполагал, что пакет) и об исключениях. Исключения могут происходить при любом вызове JNI (env->...), поэтому проверьте документацию о том, как бороться с исключениями (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 );
}

Это хороший пример: https://github.com/NickZt/MyJNACallbackTest Этот же код подробно описан здесь: https://www.hackster.io/user2657268124/a-beginner-s-guide-to-implement-jni-callbacks-in-android-cd8226

Другие вопросы по тегам