#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.