Я только начинаю работать с JNI, и у меня возникла следующая проблема.
У меня есть библиотека C ++ с простым классом. У меня есть три метода JNI, вызываемых из проекта Java Android, которые инсталлируют указанный класс, вызывают метод в созданном классе и, соответственно, уничтожают его. Я сохраняю глобальную ссылку на этот объект, поэтому он будет доступен мне в двух других методах JNI.
Подозреваю, что не могу этого сделать. Когда я запускаю приложение, я получаю ошибку времени выполнения (использованная ссылка устарела), и я подозреваю, что это связано с тем, что глобальная ссылка недействительна при последующих вызовах других методов JNI.
Является ли единственный способ добиться того, чего я хочу (заставить объект жить через несколько вызовов JNI), фактически передать обратно указатель на созданный экземпляр класса обратно в Java, оставить его там, а затем передать его обратно функциям JNI? Если да, то ничего страшного, я хочу убедиться, что не могу сделать это с глобальной ссылкой, и я не просто что-то упускаю.
Я прочитал документацию и главы о глобальных / локальных ссылках в JNI, но похоже, что это применимо только к классам Java, а не к моим собственным, родным классам C ++, или я ошибаюсь.
Вот код, если мое описание неясно (резюмируя, мне интересно, будет ли вообще работать этот механизм сохранения объектов):
Джава:
package com.test.ndktest;
import android.app.Activity;
import android.os.Bundle;
import android.app.AlertDialog;
public class NDKTestActivity extends Activity {
static {
System.loadLibrary("ndkDTP");
}
private native void initializeTestClass();
private native void destroyTestClass();
private native String invokeNativeFunction();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initializeTestClass();
String hello = invokeNativeFunction();
destroyTestClass();
new AlertDialog.Builder(this).setMessage(hello).show();
}
}
Заголовок JNI:
extern "C" {
jstring Java_com_test_ndktest_NDKTestActivity_initializeTestClass(JNIEnv* env, jobject javaThis);
jstring Java_com_test_ndktest_NDKTestActivity_destroyTestClass(JNIEnv* env, jobject javaThis);
jstring Java_com_test_ndktest_NDKTestActivity_invokeNativeFunction(JNIEnv* env, jobject javaThis);
};
Тело JNI:
#include <string.h>
#include <jni.h>
#include <ndkDTP.h> //JNI header
#include <TestClass.h> //C++ header
TestClass *m_globalTestClass;
void Java_com_test_ndktest_NDKTestActivity_initializeTestClass(JNIEnv* env, jobject javaThis) {
m_globalTestClass = new TestClass(env);
}
void Java_com_test_ndktest_NDKTestActivity_destroyTestClass(JNIEnv* env, jobject javaThis) {
delete m_globalTestClass;
m_globalTestClass = NULL;
}
jstring Java_com_test_ndktest_NDKTestActivity_invokeNativeFunction(JNIEnv* env, jobject javaThis) {
jstring testJS = m_globalTestClass->getString();
return testJS;
}
Заголовок C ++:
class TestClass
{
public:
jstring m_testString;
JNIEnv *m_env;
TestClass(JNIEnv *env);
jstring getString();
};
Тело C ++:
#include <jni.h>
#include <string.h>
#include <TestClass.h>
TestClass::TestClass(JNIEnv *env){
m_env = env;
m_testString = m_env->NewStringUTF("TestClass: Test string!");
}
jstring TestClass::getString(){
return m_testString;
}
Спасибо