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

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

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 中正确创建 java 字符串数组(即 jstring 对象数组,即表示 jstring 对象数组的对象).我一直在使用以下资源,并从中构建了可编译的代码.我不确定之后发生的错误是由于语法不正确还是由于完全不同的原因.由于代码大部分是孤立的,我假设语法不正确.

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.

(Suns 原生编程文档 & Suns JNI 文档)

代码可以编译,但在通过FindClass"代码行后,会发送一个 SIGSEGV 信号,该信号会终止 C 进程:

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

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.

编辑

我的大部分问题是调试此代码导致了问题.我没有时间缩小复制因素,但是通过 eclipse 在 gdb-client 中跨过 JNI 代码不起作用.

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.

推荐答案

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

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

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

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.

相关文章