Возврат массива строк в методе JNI

Мне нужно получить список строк (char*) из С++ и вернуть его в Java.

Как я могу это сделать?

Я думаю, что одно из решений - вернуть заранее определенную большую строку, например: "[item1][item2]" и сделать разделение на Java, но это не похоже на правильный подход.


person Marcos Vasconcelos    schedule 18.05.2011    source источник


Ответы (2)


Посмотрите NewObjectArray в документе JNI.

По сути, вы можете вернуть из функции JNI массив строк (Java), а затем преобразовать его в List или любой другой тип коллекции.

Код Педо:

Джава:

....
public List<String> getFooAsList(){
  return new ArrayList(this.getData());
}  
private native String[] getData();

JNI

#include <jni.h>


  JNIEXPORT jobjectArray JNICALL 
               como_foo_bar_getData
  (JNIEnv *env, jobject jobj){

    jobjectArray ret;
    int i;

    char *data[5]= {"A", "B", "C", "D", "E"};

    ret= (jobjectArray)env->NewObjectArray(5,env->FindClass("java/lang/String"),env->NewStringUTF(""));

    for(i=0;i<5;i++) env->SetObjectArrayElement(ret,i,env->NewStringUTF(data[i]));

    return(ret);
 }

Не испытано!!!

Дайте мне знать, если это работает для вас

С уважением

person Francesco Laurita    schedule 18.05.2011
comment
Еще один вопрос, какой тип данных я использую в своем методе привязки jni_onLoad? { getTOC, ()‹здесь›, reinterpret_cast‹void*›(& Java_com_rmsdk_wrapper_RMServices_getTOC)} - person Marcos Vasconcelos; 18.05.2011
comment
Я только что нашел это ()[Ljava/lang/String; - person Marcos Vasconcelos; 18.05.2011
comment
Другой вопрос: что произойдет, если SetObjectArrayElement выкинет исключение? Как очищается выделенный массив? Вы возвращаете ret или NULL? - person iboisver; 20.03.2012
comment
char *data[5]= {A, B, C, D, E}; теперь устарело. Это будет отображать предупреждающие сообщения в консоли gradle. - person naseer mohammad; 09.07.2018

ret= (jobjectArray)env->NewObjectArray(5,env->FindClass("java/lang/String"),env->NewStringUTF(""));

Я думаю, что начальный элемент инициализирован как "" (пустая строка)

env->NewStringUTF("")

не требуется, так как вы присваиваете новое значение элементу массива сразу после:

for(i=0;i<5;i++) env->SetObjectArrayElement(ret,i,env->NewStringUTF(data[i]));

В этом случае будет достаточно простого «NULL», так как указанный начальный элемент будет выбран для сборки мусора, как только будет выполнена следующая строка. Это похоже на написание следующего кода в Java:

int i = 0;
i = 1;

Или хуже:

Object object = new BigObjectVeryHeavyToInitialize();
object = new AnotherObject();

Ваша любимая IDE выдаст вам небольшое предупреждение об этом.

person Laurent_Psy    schedule 14.02.2014
comment
Точно. Выделение памяти для пустых строк инициализации может привести к утечке памяти, поскольку они не удаляются автоматически. - person sudar; 07.10.2016