在JNI方法中返回一个字符串数组

23

我需要从 C++ 获取一个字符串列表(char*),并将其返回给 Java。

我该怎么做?

我认为一种解决方案是返回一个预定义的大字符串,类似于 "[item1] [item2]",然后在 Java 上进行分割,但这似乎不是正确的方法。

2个回答

36

请查看JNI文档中的NewObjectArray

基本上,您可以从JNI函数返回一个字符串数组(Java),然后将其转换为List或任何其他类型的集合。

伪代码:

Java:

....
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);
 }

未经测试!!!

如果可以,请告诉我。

谢谢!


只有一个问题,我的jni_onLoad绑定方法中使用的数据类型是什么?{ "getTOC", "()<这里>", reinterpret_cast<void*>(& Java_com_rmsdk_wrapper_RMServices_getTOC)} - Marcos Vasconcelos
2
我刚刚发现它是"()[Ljava/lang/String;"。 - Marcos Vasconcelos
1
另一个问题:如果SetObjectArrayElement抛出异常会发生什么?分配的数组如何清理?你返回ret还是NULL - iboisver
1
char *data[5]= {"A", "B", "C", "D", "E"}; 现在已经过时了。这将在Gradle控制台中显示警告消息。 - naseer mohammad

5
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会为此向你发出小小的警告。


1
没错。为空初始化字符串分配的内存可能会导致内存泄漏,因为它们不会自动删除。 - sudar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接