поддерживать какой-то объект C ++ в течение нескольких вызовов jni - PullRequest
5 голосов
/ 06 декабря 2011

Мой Java-код вызовет существующий код C ++ для анализа файла.это сгенерирует объект, который хранит много данных.Я вызову второй метод jni для доступа к таким данным. Когда я вызываю второй метод, мне нужно снова проанализировать файл.это, очевидно, правильное поведение.

Есть ли способ справиться с этим?Кстати, я недавно на C ++.

Ответы [ 2 ]

8 голосов
/ 06 декабря 2011

Я не уверен, правильно ли я понимаю ваш вопрос.Но я думаю, что вы хотите сделать, чтобы поддерживать какой-то объект C ++ в течение нескольких вызовов jni.

Вы можете сделать несколько вещей.Сначала проанализируйте ваш файл и сохраните ваш объект c ++ в глобальной переменной.Это простейшее решение, но не очень хорошее.

Вы также можете перенести жизненный цикл вашего объекта c ++ в java.

jlong java_some_class_jni_method(...)
{
    .... parse your text file ....
    MyParseclass* cls = new MyParseclass(...);
    ....
    return (jlong) cls;
}

Но имейте в виду, что вам нужно удалить этоснова родной класс с ++.Так что вам нужен метод jni для этого и обязательно вызовите его.

void java_some_calls_jni_method(..., jlong clsPtr)
{
    MyParseclass* cls = (MyParseclass*)clsPtr;
    ... do maybe do something with cls and access the data...
    delete cls; // do not use the jlong again in any call
}

Кстати: было бы гораздо полезнее, если бы вы опубликовали какой-то код.Но я надеюсь, что этот псевдокод здесь немного поможет.

3 голосов
/ 20 июня 2017

Этот вопрос очень похож на этот

Вот мое решение для сохранения объектов на C ++, чтобы ссылаться на них из нескольких вызовов JNI:

Java

На стороне Java я создаю класс с указателем long, чтобы сохранить ссылку на объект C ++.Оборачивая методы C ++ в класс Java, мы можем использовать методы C ++ в нескольких действиях.Обратите внимание, что я создаю объект C ++ в конструкторе и удаляю объект при очистке.Это очень важно для предотвращения утечек памяти:

public class JavaClass {
    // Pointer (using long to account for 64-bit OS)
    private long objPtr = 0;

    // Create C++ object
    public JavaClass() {
        createCppObject();
    }

    // Delete C++ object on cleanup
    public void cleanup() {
        deleteCppObject();
        this.objPtr = 0;
    }

    // Native methods
    public native void createCppObject();
    public native void workOnCppObject();
    public native void deleteCppObject();

    // Load C++ shared library
    static {
        System.loadLibrary("CppLib");
    }

}

C ++

На стороне C ++ я определяю функции для создания, изменения и удаления объекта,Важно отметить, что мы должны использовать new и delete для хранения объекта в памяти HEAP, чтобы поддерживать его в течение всего жизненного цикла экземпляров класса Java.Я также храню указатель на CppObject прямо в JavaClass, используя getFieldId, SetLongField и GetLongField:

// Get pointer field straight from `JavaClass`
jfieldID getPtrFieldId(JNIEnv * env, jobject obj)
{
    static jfieldID ptrFieldId = 0;

    if (!ptrFieldId)
    {
        jclass c = env->GetObjectClass(obj);
        ptrFieldId = env->GetFieldID(c, "objPtr", "J");
        env->DeleteLocalRef(c);
    }

    return ptrFieldId;
}

// Methods to create, modify, and delete Cpp object
extern "C" {

    void Java_com_test_jnitest_JavaClass_createCppObject(JNIEnv *env, jobject obj) {
        env->SetLongField(obj, getPtrFieldId(env, obj), (jlong) new CppObject);
    }

    void Java_com_test_jnitest_JavaClass_workOnCppObject(JNIEnv *env, jobject obj) {
        CppObject* cppObj = (CppObject*) env->GetLongField(obj, getPtrFieldId(env, obj));

        // Write your code to work on CppObject here
    }

    void Java_com_test_jnitest_JavaClass_deleteCppObject(JNIEnv *env, jobject obj) {
        CppObject* cppObj = (CppObject*) env->GetLongField(obj, getPtrFieldId(env, obj));

        delete cppObj;
    } 

}

ПРИМЕЧАНИЯ:

  • В отличие от Java, C ++ не имеет сборки мусора, и объект будет жить в памяти HEAP, пока вы не используете delete.
  • Я использую GetFieldID, SetLongFieldи GetLongField для хранения ссылки на объект из C ++, но вы также можете хранить указатель на объект jlong из Java, как обсуждалось в других ответах.
  • В моем конечном коде я реализовал класс JavaObjectкак Parcelable, чтобы передать мой класс нескольким занятиям, используя Intent с дополнительными функциями.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...