当前位置: 首页 > 知识库问答 >
问题:

在C++中创建字节[][],并使用JNI将其返回到Java

尤钱明
2023-03-14
byte[] arg = getRandomByteArray();
Object[] retVal = x.method(arg);

因此,我创建了我的对象数组,每个对象都被初始化为一个新字节[1024]:

jobjectArray retVal = env->NewObjectArray(numSegs, env->FindClass("[Ljava/lang/Object;"), env->NewByteArray(1024));

然后,我遍历这个数组中的所有索引,执行如下操作:

jbyteArray tmp = (jbyteArray) env->GetObjectArrayElement(retVal, i);
env->SetByteArrayRegion(tmp, 0, size, (jbyte*) sourceBuffer);
env->SetObjectArrayElement(retVal, i, (jobject) tmp); // <--- Questionable line

在大多数情况下,一切都很好。但是,如果我希望每个字节数组都是可变长度的呢?也就是说,我希望字节数组的数组是“锯齿状”的。我将什么作为最后一个参数传递给NewObjectArray()作为初始值?我尝试传递0作为初始值,以防止在创建jobjectArray时进行初始化,然后分配新的jbyteArray对象传递给SetObjectArrayElement(),但这只会在每次尝试调用SetObjectArrayElement时引发ArrayStoreException。实际上,即使为tmp对象分配一个新的jbyteArray(而不是GetObjectArrayElement()中的jbyteArray)也会在调用SetObjectArrayElement()时引发相同的异常。最后一行代码会出现问题有什么原因吗?不能用jbyteArray作为参数调用SetObjectArrayElement()吗?

共有1个答案

章振
2023-03-14

我刚刚成功地通过JNI返回了字节数组的数组。字节数组的初始大小与您的字节数组无关,因为在填充jobject数组时,您将用一个新的字节数组替换它:

static jbyteArray NewJavaStringBytes(JNIEnv* env, const char *src) {
    jbyteArray retVal = (*env)->NewByteArray(env, strlen(src));
    jbyte *buf = (*env)->GetByteArrayElements(env, retVal, NULL);
    strcpy(buf, src);
    printf("    NewJavaStringBytes: Created java byte array: %s.\n", buf);
    (*env)->ReleaseByteArrayElements(env, retVal, buf, 0);

    return retVal;
}

JNIEXPORT jobjectArray JNICALL Java_TestJniString_printStringArray
  (JNIEnv *env, jobject thisObj, jobjectArray jObjArr) {
    int numStr = (*env)->GetArrayLength(env, jObjArr);
    int idx = 0;
    jobjectArray strArr = NULL;
    jbyte *curStr = NULL;
   jclass arrayElemType = (*env)->FindClass(env, "[B");

    const char *retStrs[] = {"one", "two", "three", "twenty-five", "TESTING!!"};
    const int RET_LEN = sizeof(retStrs) / sizeof(char *);

    printf("Creating java object array of %d items.\n", RET_LEN);
    //Create new array of byte array
    jobjectArray testArray = (*env)->NewObjectArray(env,
                                                    RET_LEN,
                                                    arrayElemType,
                                                    (*env)->NewByteArray(env, 1) );

    for (idx = 0; idx < RET_LEN; ++idx) {   
        printf("Creating java byte array %d from str: %s.\n", idx, retStrs[idx]);
        jbyteArray str = NewJavaStringBytes(env, retStrs[idx]);
        (*env)->SetObjectArrayElement(env, testArray, idx, str);
        (*env)->DeleteLocalRef(env, str);
    }

    printf("printStringArray: Printing %d strings:\n", numStr);
    for (idx = 0; idx < numStr; ++idx) {
        strArr = (*env)->GetObjectArrayElement(env, jObjArr, idx);
        curStr = (*env)->GetByteArrayElements(env, strArr, NULL);
        printf("    %s.\n", curStr);
        (*env)->ReleaseByteArrayElements(env, (jbyteArray)strArr, curStr, 0);
    }

    (*env)->DeleteGlobalRef(env, arrayElemType);

    return testArray;
}

此示例采用字节数组数组并返回字节数组数组。注意这是在C中(不是C++),所以jni调用是(*env)->(env,...);。在C++中,包装器简化了调用。另外,请注意,这假定java代码在发送到本机层之前在字符串的字节数组版本上添加了空终止符。如果您不能指望这一点,那么您必须在C/C++代码中手动添加null项,因为Java在从String转换时不会对Byte[]这样做。

希望能有所帮助。

 类似资料:
  • 问题内容: 我目前在一个项目中同时使用C 和Java,并且希望能够将包含在C 中的对象发送到我的Java接口,以便通过GUI对其进行修改,然后将所做的修改发送回C ++中。 到目前为止,我一直没有通过JNI接口向Java返回int或boolean值。这次我必须通过接口发送对象。我已经在C ++和Java中提供了类似的类定义。 我想知道如何创建对象,以便可以在Java中使用它。 在C ++中,我有:

  • 问题内容: 我看到许多人都遇到过类似的问题,但是我还没有尝试确切地找到我想要的东西。 因此,我有一个读取输入图像并将其转换为字节数组的方法: 我现在要做的是将其转换回BufferedImage(我有一个需要此功能的应用程序)。请注意,“ test”是字节数组。 但是,这将返回以下异常: 这是因为BufferedImage img为空。我认为这与以下事实有关:在我从BufferedImage到字节数

  • 问题内容: 我正在尝试使用JNI函数创建Java类,并使用DeviceId.java构造函数方法设置该类的某些属性。我可以使用GetMethodID获取构造函数方法,但是如何创建Device.java的新实例,然后设置属性(setId和setCache)。目标是将完全填充的Device.java对象的实例返回给调用者。有任何想法吗? JNI功能: Java类: 问题答案: 调用时,您为two-ar

  • 这已经超出我的想象了,我们开始吧。 我正在用C语言设置一个函数指针,该指针带有一个Java接口对象,看起来像Java端的接口对象: 其中,是只有一种方法的接口: 而指的是Java本机方法,它在C端反映如下: 所有这些都是基于JNI中使用接口实现回调函数编写的 我已经尝试在C端调用Java中定义的方法,它可以工作(就像上面的链接一样),但是现在我正在尝试在C下设置这样的上的值 因此,稍后我想把作为一

  • 这是我的职能: 并且它总是在这个LOG:。我在这里做错了什么?这就是我试图在NDK中实现的目标: public byte[]i420 tonv 21(final byte[]input,byte[] output,final int width,final int height){ if(output = = null){ output = new byte[input . length];} f

  • 问题内容: 我发现了大量有关如何在JNI中生成2D基本数组并将其返回给Java的文档。但是这些信息无法描述如何在 C中* 为上下文传递 已存在的 2D浮点数组(float **)。 * 为了明确描述我的问题,我将添加一些我想实现的 C 伪代码: 考虑到我无法找到任何描述这种情况的信息,我认为这不是直截了当的。 感谢您提供任何有用的信息。 问题答案: 感谢Timo的帮助和链接。为了后代,我添加了一个