java 从本机代码 (JNI/NDK) 创建、填充和返回二维字符串数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6070679/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 14:11:32  来源:igfitidea点击:

Create, populate and return 2D String array from native code (JNI/NDK)

javastringmultidimensional-arrayjava-native-interface

提问by Graeme

I'm finding this particular bit of code quite difficult (Not least of which because I only started playing with C a week ago).

我发现这段特殊的代码非常困难(尤其是因为我一周前才开始使用 C)。

I've been trying hard to find the right syntax to correctly create a java string array in C (i.e., an array of jstring objects, i.e. an object which represents an array of jstring objects). I've been using the following resources and from them I've constructed code which compiles. I'm not sure if the error which occurs afterwards is due to the syntax being incorrect or because of a completely separate reason. Since the code is mostly in isolation I'm assuming the syntax is incorrect.

我一直在努力寻找正确的语法来在 C 中正确创建一个 java 字符串数组(即 jstring 对象数组,即表示 jstring 对象数组的对象)。我一直在使用以下资源,并从中构建了可编译的代码。我不确定之后发生的错误是由于语法不正确还是完全不同的原因造成的。由于代码大部分是孤立的,我假设语法不正确。

(Suns Native Programming Documentation& Suns JNI documentation)

( Suns Native Programming 文档& Suns JNI 文档)

The code compiles but after passing the "FindClass" line of code a SIGSEGV signal is sent which kills the C process:

代码编译但在传递“FindClass”代码行后,会发送一个 SIGSEGV 信号,该信号会终止 C 进程:

jint size = 5;
jclass StringObject = (*env)->FindClass(env, "java/lang/String");
jobjectArray sampleMessage = (*env)->NewObjectArray(env, size, StringObject, NULL);
jobjectArray returnArray = (jobjectArray) (*env)->NewObjectArray(env, messageCount, &sampleMessage, 0);

Could anyone point me to a useful resource for this? Or confirm the syntax is correct.

任何人都可以指出我对此有用的资源吗?或者确认语法正确。

EDIT

编辑

I large part of my problem was that debugging this code caused the problem. I don't have time to narrow down the reproducing factor but stepping over JNI code in a gdb-client through eclipse DOESN'T work.

我的问题的很大一部分是调试此代码导致了问题。我没有时间缩小再现因素的范围,但是通过 eclipse 在 gdb-client 中单步执行 JNI 代码是行不通的。

回答by fizzer

To get a jclass for the row type, you can call GetObjectClass()on one of the rows. This works:

要获取行类型的 jclass,您可以调用GetObjectClass()其中一行。这有效:

Main.java

主程序

public class Main {

    static {
        System.loadLibrary("mynative");
    }

    private static native String[][] getStringArrays();

    public static void main(String[] args) {
        for (String[]  array : getStringArrays())
            for (String s : array)
                System.out.println(s);
    }
}

mynative.c

mynative.c

static jobjectArray make_row(JNIEnv *env, jsize count, const char* elements[])
{
    jclass stringClass = (*env)->FindClass(env, "java/lang/String");
    jobjectArray row = (*env)->NewObjectArray(env, count, stringClass, 0);
    jsize i;

    for (i = 0; i < count; ++i) {
        (*env)->SetObjectArrayElement(env, row, i, (*env)->NewStringUTF(env, elements[i]));
    }
    return row;
}

JNIEXPORT jobjectArray JNICALL Java_Main_getStringArrays(JNIEnv *env, jclass klass)
{
    const jsize NumColumns = 4;
    const jsize NumRows = 2;

    const char* beatles[] = { "John", "Paul", "George", "Ringo" };
    jobjectArray jbeatles = make_row(env, NumColumns, beatles);

    const char* turtles[] = { "Leonardo", "Raphael", "Michaelangelo", "Donatello" };
    jobjectArray jturtles = make_row(env, NumColumns, turtles);

    jobjectArray rows = (*env)->NewObjectArray(env, NumRows, (*env)->GetObjectClass(env, jbeatles), 0);

    (*env)->SetObjectArrayElement(env, rows, 0, jbeatles);
    (*env)->SetObjectArrayElement(env, rows, 1, jturtles);
    return rows;
}

Building, error handling omitted for clarity.

为清楚起见,省略了构建、错误处理。