Как вызвать функцию обратного вызова Java-апплета из собственного кода C / C с использованием JNI.

#java #c #c #applet #java-native-interface

#java #c #c #апплет #java-native-interface

Вопрос:

Как вызвать функцию обратного вызова Java-апплета из собственного кода C / C с использованием JNI. Пожалуйста, дайте мне знать, как это можно сделать правильно. Пожалуйста, любой фрагмент кода был бы полезен.

 // Java Applet code

public class TestApp extends Applet {

    private native void TestMethod(int nValue);

    public void callback(int nValue) {
            // DISPLAY SOME MESSAGE FROM NATIVE DLL RECEIVED

    }

     static {
        System.load("c/temp/TestDll.dll");
  }
}
  

// TestDll.cpp

 JNIEnv *g_env;
jobject g_object;
jmethodID g_method;




   JNIEXPORT void JNICALL
    Java_Callbacks_TestMethod(JNIEnv *env, jobject obj, jint Value)
    {
        jclass cls = (*env)->GetObjectClass(env, obj);
        jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V");      

        g_env = env;
        g_Object = obj;
        g_method = mid
    }

        // Cannot be called within the above function
    void TestDllCallbackFunction (int nValue)
    {

            // This is where i want to call the Java callback function… would the below work???
        (*g_env)->CallVoidMethod(g_env, g_object, g_method, ((jint)Value);
    }
  

Комментарии:

1. В чем проблема с вашим кодом? В принципе, это правильно, так, как вы это делаете. Помимо того факта, что вы не должны хранить объекты Java в собственных глобальных переменных. Вы не можете гарантировать, что GC не удалит их.

2. Как я могу вызвать функцию обратного вызова Java в локальной встроенной функции, если у меня нет ссылки на текущие объекты Java. Пожалуйста, опишите, приведя пример кода. Спасибо.

3. Посмотрите здесь java.sun.com/docs/books/jni/html/refs.html . Вам нужны глобальные ссылки на ваш объект.

4. Спасибо за ответ: mKaes. Я сделал объект глобальной ссылкой, но поток не выходит из CallVoidMethod() . Пожалуйста, дайте мне знать, если у вас есть какие-либо подсказки к этому. Пожалуйста, посмотрите Ниже код, так как здесь недостаточно места, чтобы опубликовать его с этим комментарием

5. JNIEnv *g_env; jobject g_object; jmethod g_method; <pre><code> JNIEXPORT void JNICALL Java_Callbacks_TestMethod(JNIEnv *env, jobject obj, значение jint) { g_env = env; jclass cls = (*env)->GetObjectClass (env, obj); g_Object = (* env)->NewGlobalRef(obj); // ЗДЕСЬ g_method = (* env)->GetMethod(env, cls, «обратный вызов», «(I) V»); } // Не может быть вызван в рамках вышеупомянутой функции void TestDllCallbackFunction (int nValue) { Log(«IN»); nValue =5; (* g_env)->CallVoidMethod(g_env, g_object, g_method, ((jint)nValue); Log(«OUT»); // Оператор log НИКОГДА НЕ выполняется. }

Ответ №1:

Вам также следует рассмотреть другое решение в качестве альтернативы обратным вызовам с C на Java:

  • Создайте дополнительный поток Java для ожидания ответа от C
  • Пусть этот поток Java вызывает функцию C , которая блокирует переменную условия (или аналогичную, в зависимости от вашей ОС), пока ответ не будет готов к возврату.
  • Если вы хотите вызвать обратный вызов, пусть приведенная выше функция C имеет данные и сигнализирует о переменной условия. Затем он может возвращать данные.

Обратные вызовы через JNI, безусловно, могут быть выполнены, но я думаю, что они добавляют ненужную сложность. Используя описанный выше метод, вы можете более четко разделить вещи, IMHO.