在C+中创建字节[]+;并使用JNI将其返回给Java 我有一个JNI函数,用C++编写,它把一个字节数组作为输入,对它进行分段,并返回一个字节数组到java。

在C+中创建字节[]+;并使用JNI将其返回给Java 我有一个JNI函数,用C++编写,它把一个字节数组作为输入,对它进行分段,并返回一个字节数组到java。,java,c++,java-native-interface,Java,C++,Java Native Interface,JNIEXPORT jobjectArray JNICALL Java_class_方法(JNIEnv*env、jobject o、jbyteArray dataToSegment) 在Java方面,它非常简单: byte[] arg = getRandomByteArray(); Object[] retVal = x.method(arg); 现在,我发现JNI部分有点棘手。我打算创建一个对象数组,每个对象都是字节数组。这是因为JNI只定义了有限数量的Java类型。有jbyteArray类

JNIEXPORT jobjectArray JNICALL Java_class_方法(JNIEnv*env、jobject o、jbyteArray dataToSegment)

在Java方面,它非常简单:

byte[] arg = getRandomByteArray();
Object[] retVal = x.method(arg);
现在,我发现JNI部分有点棘手。我打算创建一个对象数组,每个对象都是字节数组。这是因为JNI只定义了有限数量的Java类型。有jbyteArray类型和jobjectArray类型,但没有JarrayOfByteArray类型

因此,我创建了对象数组,每个对象被初始化为一个新字节[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
jbyteArray tmp=(jbyteArray)env->GetObjectArrayElement(retVal,i);
env->SetByteArrayRegion(tmp,0,大小,(jbyte*)源缓冲区);

env->SetObjectArrayElement(retVal,i,(jobject)tmp);//SetObjectArrayElement(retVal,i,(jobject)env->NewByteArray(size));//不起作用。

如果您可以选择使用JNA而不是JNI,您应该能够使用类似于JNA API文档页面中提供的示例的内容:


“要映射本机多维数组,请使用一个一维Java数组,该数组的元素数量相当于完整的本机数组”

我刚刚通过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;
}
静态jbyterarray 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:创建的java字节数组:%s.\n”,buf);
(*env)->按技术要求发布(env、retVal、buf、0);
返回返回;
}
JNIEXPORT jobjectArray JNICALL Java_TestJniString_printStringArray
(JNIEnv*env,jobject thisObj,jobject数组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[]={“一”、“二”、“三”、“二十五”、“测试!!”};
常量int RET_LEN=sizeof(retStrs)/sizeof(char*);
printf(“创建%d项的java对象数组。\n”,RET_LEN);
//创建字节数组的新数组
jobjectArray testArray=(*env)->NewObjectArray(env,
雷特伦,
arrayElemType,
(*env)->NewByteArray(env,1));
对于(idx=0;idxSetObjectArrayElement(env、testArray、idx、str);
(*env)->DeleteLocalRef(env,str);
}
printf(“printStringArray:打印%d个字符串:\n”,numStr);
对于(idx=0;idxGetObjectArrayElement(env、jObjArr、idx);
curStr=(*env)->GetByteArrayElements(env,strArr,NULL);
printf(“%s.\n”,curStr);
(*env)->ReleaseByteArrayElements(env,(jbyteArray)strArr,curStr,0);
}
(*env)->DeleteGlobalRef(env,arrayElemType);
返回测试阵列;
}
本例采用字节数组数组并返回字节数组数组。请注意,这是C语言(不是C++),因此jni调用为(*env)->(env,…)注意,这是假设java代码在发送到原生层之前将字节终止符添加到字符串的字节数组版本中。如果不能指望,那么必须手动添加C/C++代码中的空项,因为java在从C++转换时不会对字节[]进行此操作。
希望这能有所帮助。

谢谢,但不幸的是我在这里被JNI困住了。@SzymonSmakolski使用JNI代码中的NewDirectByteBuffer来分配缓冲区。基于我[有限]的理解,NewDirectByteBuffer在本机端分配内存。我希望JVM分配一堆Java字节[]我可以塞进对象[]中的对象。您建议的方法是让我使用C++的新操作符(而不是JVM)分配每个字节数组。我宁愿让JVM来处理实际在Java端结束的任何数据的分配。