Передающие указатели между C и Java через JNI

Вы могли сослаться на средства управления в основной странице этот путь:

void Page_Load()
{
    ContentPlaceHolder cph;
    Literal lit;

    cph = (ContentPlaceHolder)Master.FindControl("ContentPlaceHolder1");

    if (cph != null) {
        lit = (Literal) cph.FindControl("Literal1");
        if (lit != null) {
            lit.Text = "Some <b>HTML</b>";
        }
    }

}

В этом примере необходимо поместить Элемент управления литерал в ContentPlaceholder.

68
задан Volker 27 October 2009 в 18:39
поделиться

4 ответа

Я использовал следующий подход:

в вашем коде JNI создайте структуру, которая будет содержать ссылки на нужные вам объекты. Когда вы впервые создаете эту структуру, верните ее указатель на java как long . Затем из java вы просто вызываете любой метод с этим long в качестве параметра, а в C приводите его к указателю на вашу структуру.

Структура будет в куче, поэтому она не будет очищаться между различными вызовами JNI.

РЕДАКТИРОВАТЬ: Я не думаю, что вы можете использовать long ptr = (long) & address; , поскольку адрес - статическая переменная. Используйте его так, как предлагал Gunslinger47, то есть создайте новый экземпляр класса или структуры (используя new или malloc) и передайте его указатель.

44
ответ дан 24 November 2019 в 14:20
поделиться

Если вы распределяете память динамически (в куче) внутри собственной функции, она не удаляется. Другими словами, вы можете сохранять состояние между различными вызовами собственных функций, используя указатели, статические переменные и т. Д.

Подумайте об этом по-другому: что вы могли бы безопасно сохранить в вызове функции, вызванной из другого C ++ программа? То же самое и здесь. Когда функция завершается, все в стеке для этого вызова функции уничтожается; но все, что находится в куче, сохраняется, если вы явно не удалите его.

Краткий ответ: до тех пор, пока вы не освободите результат, возвращаемый вызывающей функции, он останется действительным для повторного входа позже. Просто не забудьте очистить его, когда закончите.

6
ответ дан 24 November 2019 в 14:20
поделиться

Java не знает, что делать с указателем, но она должна иметь возможность хранить указатель на возвращаемое значение нативной функции, а затем передать его другой нативной функции для обработки. Указатели C - это не что иное, как числовые значения в ядре.

Другой участник должен сообщить вам, будет ли очищена указанная на графическую память между вызовами JNI и будут ли какие-либо обходные пути.

10
ответ дан 24 November 2019 в 14:20
поделиться

В C++ вы можете использовать любой механизм для выделения/освобождения памяти: стек, malloc/free, new/delete или любую другую пользовательскую реализацию. Единственное требование - если вы выделили блок памяти с помощью одного механизма, вы должны освободить его с помощью того же механизма, поэтому вы не можете вызвать free на стековой переменной и не можете вызвать delete на malloced памяти.

JNI имеет свои собственные механизмы выделения/освобождения памяти JVM:

  • NewObject/DeleteLocalRef
  • NewGlobalRef/DeleteGlobalRef
  • NewWeakGlobalRef/DeleteWeakGlobalRef

Они следуют тому же правилу, единственная загвоздка в том, что локальные ссылки могут быть удалены "массово" либо явно, с помощью PopLocalFrame, либо неявно, при выходе из родного метода.

JNI не знает, как вы выделили память, поэтому не может освободить ее при выходе из функции. Переменные стека, очевидно, будут уничтожены, поскольку вы все еще пишете на C++, но память GPU останется действительной.

Единственная проблема заключается в том, как получить доступ к памяти при последующих вызовах, и тут вы можете воспользоваться предложением Gunslinger47:

JNIEXPORT jlong JNICALL Java_MyJavaClass_Function1() {
    MyClass* pObject = new MyClass(...);
    return (long)pObject;
}

JNIEXPORT void JNICALL Java_MyJavaClass_Function2(jlong lp) {
    MyClass* pObject = (MyClass*)lp;
    ...
}
15
ответ дан 24 November 2019 в 14:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: