Я использую JNI в своем Java-коде для вызова собственного кода C. Это прекрасно работает, и я делаю некоторую обработку в коде C. Код C регистрирует прослушиватель событий, поэтому я уведомляюсь каждый раз, когда новый результат готов в части C.
Теперь я хочу вернуть результаты в код Java следующим образом:
void notifyGazeEvent()
{
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mid = (*env)->GetMethodID(env, cls, "newGazeEvent", "(I)V");
if (mid == 0)
{
return;
}
printf("In C, about to enter Java");
(*env)->CallVoidMethod(env, obj, mid, 1);
}
Теперь проблема заключается в следующем: я не знаю, откуда взять объект JNIEnv и объект jObject. Это передается, когда я сначала вызываю код C:
JNIEXPORT void JNICALL
Java_a_b_C_doCalculation(JNIEnv *env, jobject obj)
{
// here I register all the handlers etc,
}
Но я не знаю, как я могу передать ссылки до моего метода, который выполняет обратный вызов Java.
Чтобы сохранить jobject obj
за пределами функции Java_a_b_C_doCalculation
, вам нужно создать глобальную ссылку, так как все объекты (JNIEnv также) перестают действовать после возвращения функции. Глобальную ссылку можно легко создать с помощью NewGlobalRef
.
Указатель JNIEnv
не может быть сохранен таким образом, также если поток, который вызывает notifyGazeEvent()
был создан в C, вы должны сначала связать поток с JVM. Сохранить JavaVM *vm
указатель из JNI_OnLoad
, и либо optain в JNIEnv с GetEnv
или присоединить вновь созданную нить AttachCurrentThread (AsDaemon).