【问题标题】:Create, populate and return 2D String array from native code (JNI/NDK)从本机代码 (JNI/NDK) 创建、填充和返回二维字符串数组
【发布时间】:2011-08-29 13:34:31
【问题描述】:

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

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

(Suns Native Programming Documentation & Suns JNI documentation)

代码可以编译,但在通过“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);

谁能指出我对此有用的资源?或者确认语法正确。

编辑

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

【问题讨论】:

    标签: java string multidimensional-array java-native-interface


    【解决方案1】:

    要获取行类型的 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

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

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

    【讨论】:

    • 很好的答案。非常感谢!
    • 此代码的变体在我的测试工具中效果很好。但是,当插入我的应用程序时,jclass stringClass = (*env)-&gt;FindClass(env, "java/lang/String"); 行会抛出 SIGSEGV。从我的所有检查来看,框架和应用程序的设置都是相同的。不仅如此,我什至使 c 文件足够通用,可以在线束和代码之间进行复制,而且它仍然会中断。有谁知道jclass stringClass = (*env)-&gt;FindClass(env, "java/lang/String"); 依赖什么?
    • 当代码失败时,它是从本机上下文而不是从 Java 调用的吗?如果是这样,请参阅链接的问题。你从哪里得到你的环境指针?
    • 代码在从 Java 调用后作为本机代码运行。 *env 通过 JNI 调用传递给方法。
    猜你喜欢
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 2017-03-22
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多