Jni: вызов java метода из native кода
От: Аноним  
Дата: 12.03.07 06:20
Оценка:
Добрый день, подскажите как правильно вызвать из C++ следующий java метод:
Java:
public static void callBack( char data[], int length )
{
    System.out.println( data );
    System.out.println( length );
}


Пытаюсь так:
C++:
{
….
char *data = new char[3];
data[0] = '0';
data[1] = '1';
data[2] = '2';        
int length =3;
env->CallStaticVoidMethod( jcClass, methodID, "([CI)V", data, length);        
delete data;
}


И всё это дело весело рушиться с EXCEPTION_ACCESS_VIOLATION при System.out.println(data);
Что я делаю не так?
Re: Jni: вызов java метода из native кода
От: c-smile Канада http://terrainformatica.com
Дата: 12.03.07 06:28
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:


А>Пытаюсь так:

А>C++:
А>
А>{
А>….
А>char *data = new char[3];
А>data[0] = '0';
А>data[1] = '1';
А>data[2] = '2';        
А>int length =3;
env->>CallStaticVoidMethod( jcClass, methodID, "([CI)V", data, length);        
А>delete data;
А>}
А>


А>И всё это дело весело рушиться с EXCEPTION_ACCESS_VIOLATION при System.out.println(data);

А>Что я делаю не так?

1) char в Java это далеко не char в С.
2) тебе нужно сделать NewCharArray() и его передать в Java функцию.
Re[2]: Jni: вызов java метода из native кода
От: Аноним  
Дата: 12.03.07 09:27
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>1) char в Java это далеко не char в С.

CS>2) тебе нужно сделать NewCharArray() и его передать в Java функцию.
Понял. Теперь делаю так:
jchar *data = new jchar[3];
data[0] = '1';
data[1] = '2';
data[2] = '3';
jcharArray jdata = env->NewCharArray( 3 );    
env->SetCharArrayRegion( jdata, 0, 3, data );
jint t =3;
env->CallStaticVoidMethod( javaClass, methodID, "([CI)V", jdata, t );
env->DeleteLocalRef( jdata );

Опять получаю EXCEPTION_ACCESS_VIOLATION. Самое интересное то, что переменная t (=3) тоже не передаётся ( выводится 44192356 — т.е параметр не инициализируется ?). Вроде написано правильно?
Re[3]: Jni: вызов java метода из native кода
От: bolshik Россия http://denis-zhdanov.blogspot.com/
Дата: 12.03.07 13:08
Оценка:
Здравствуйте, Аноним, Вы писали:

А>...


А>Понял. Теперь делаю так:

А>
А>jchar *data = new jchar[3];
А>data[0] = '1';
А>data[1] = '2';
А>data[2] = '3';
А>jcharArray jdata = env->NewCharArray( 3 );    
env->>SetCharArrayRegion( jdata, 0, 3, data );
А>jint t =3;
env->>CallStaticVoidMethod( javaClass, methodID, "([CI)V", jdata, t );
env->>DeleteLocalRef( jdata );
А>

А>Опять получаю EXCEPTION_ACCESS_VIOLATION. Самое интересное то, что переменная t (=3) тоже не передаётся ( выводится 44192356 — т.е параметр не инициализируется ?). Вроде написано правильно?

Неправильно:

1. Memory leak, т.к. не возвращается память, выделенная в результате

jchar *data = new jchar[3];


2. Следующий вызов просто стреляет по памяти. Его результат непредсказуем, потому что DeleteLocalRef() вообще можно не вызывать, а если уж и дергать, то только для локальных ссылок (подробнее почитать об этом можно здесь)

env->DeleteLocalRef( jdata );


Следующий код работает:

Java:


public class BBB {

    static {
        System.loadLibrary("./res/test");
    }

    public static void main(String[] args) throws Exception {
        callNative();
    }

    public static void callback(char data[], int length) {
        System.out.println(data);
        System.out.println("length = " + length);
    }

    private static native void callNative();
}


Cpp

#include "jni.h"

template<int N>
jint getArraySize(jchar (&array)[N]) {
    return (jint)(sizeof(array) / sizeof(array[0]));
}

#ifndef _Included_BBB
#define _Included_BBB
#ifdef __cplusplus
extern "C" {
#endif
    /*
    * Class:     BBB
    * Method:    callNative
    * Signature: ()V
    */
    JNIEXPORT void JNICALL Java_BBB_callNative(JNIEnv* env, jclass clazz) {
        jcharArray array = env->NewCharArray(2);
        jchar buffer[] = {'A', 'B'};
        env->SetCharArrayRegion(array, 0, getArraySize(buffer), (jchar*)buffer);
        jmethodID targetMethodId = env->GetStaticMethodID(clazz, "callback", "([CI)V");
        env->CallStaticVoidMethod(clazz, targetMethodId, array, getArraySize(buffer));
    }

#ifdef __cplusplus
}
#endif
#endif
http://denis-zhdanov.blogspot.com
Re[4]: Jni: вызов java метода из native кода
От: Аноним  
Дата: 13.03.07 06:11
Оценка:
Здравствуйте, bolshik, Вы писали:

B>Неправильно:


B>1. Memory leak, т.к. не возвращается память, выделенная в результате

delete вызывается ниже по коду (весь код не стал приводить).

B>2. Следующий вызов просто стреляет по памяти. Его результат непредсказуем, потому что DeleteLocalRef() вообще можно не вызывать, а если уж и дергать, то только для локальных ссылок (подробнее почитать об этом можно здесь)

Спасибо, просто сначала не понял...

B>Следующий код работает:

Спасибо, действительно теперь всё работает.
Re[4]: Jni: вызов java метода из native кода
От: loknalori Россия  
Дата: 18.05.07 14:16
Оценка:
Здравствуйте, bolshik, Вы писали:
А где бы почитать про ([CI)V? Т.е. про третий параметр GetStaticMethodID... На каком основании эти кракозябры набираются?
   jmethodID targetMethodId = env->GetStaticMethodID(clazz, "callback", "([CI)V");
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.