JNI Java Wrapper:如何传递 byte[] 参数

Lok*_*yak -1 c++ java java-native-interface

我需要使用 JNI 从 C++ 调用 Java API。我试图通过一个byte*如下:

爪哇

void OperateData(byte[] data, int dataLength)
{
   //Some Implementation
}
Run Code Online (Sandbox Code Playgroud)

C++

void OperateData(byte* data, int dataLength)
{
    JavaMethod* methodObj = getMethod(_T("OperateData"));
    JNIEnv* jniEnv = JvmManager::GetInstance()->GetJNIEnv();
    jobject jBuffer = jniEnv->CallObjectMethod(m_javaObject->getJObject(), methodObj->getJMethodID(), (jobject)data, (jint)dataLength);
}
Run Code Online (Sandbox Code Playgroud)

这是行不通的。它正在抛出异常。你能告诉我我做错了什么吗?

更新:我根据建议修改了 C++ 代码,如下所示。我仍然有同样的问题。还有什么问题吗?

void OperateData(byte* data, int dataLength)
{
    JavaMethod* methodObj = getMethod(_T("OperateData"));
    JNIEnv* jniEnv = JvmManager::GetInstance()->GetJNIEnv();
    jbyteArray jBuff = jniEnv->NewByteArray(dataLength);
    jniEnv->SetByteArrayRegion(jBuff, 0, dataLength, (jbyte*)data);
    jobject jBuffer = jniEnv->CallObjectMethod(m_javaObject->getJObject(), methodObj->getJMethodID(), jBuff, (jint)dataLength);
    jniEnv->ReleaseByteArrayElements(jBuff,(jbyte*)data, 0);
}
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 5

您不能简单地将原始 C/C++byte*指针类型转换为jobject表示 Java 字节数组的类型。您需要使用 JNI 函数来:

例如:

void OperateData(byte* data, int dataLength)
{
    JavaMethod* methodObj = getMethod(_T("OperateData"));
    if (!methodObj) return;
    JNIEnv* jniEnv = JvmManager::GetInstance()->GetJNIEnv();
    if (!jniEnv) return;
    jbyteArray jData = jniEnv->NewByteArray((jsize)dataLength);
    if (!jData) return;
    jniEnv->SetByteArrayRegion(jData, 0, (jsize)dataLength, (jbyte*)data);
    jniEnv->CallVoidMethod(m_javaObject->getJObject(), methodObj->getJMethodID(), jData, (jint)dataLength);
    jniEnv->DeleteLocalRef(jData);
}
Run Code Online (Sandbox Code Playgroud)

更新:在评论中,您说您更改了 Java 代码以返回 abyte[]而不是void。如果是这样,您需要相应地调整 C++ 代码,例如:

void OperateData(byte* data, int dataLength)
{
    JavaMethod* methodObj = getMethod(_T("OperateData"));
    if (!methodObj) return;
    JNIEnv* jniEnv = JvmManager::GetInstance()->GetJNIEnv();
    if (!jniEnv) return;
    jbyteArray jData = jniEnv->NewByteArray((jsize)dataLength);
    if (!jData) return;
    jniEnv->SetByteArrayRegion(jData, 0, (jsize)dataLength, (jbyte*)data);
    jobject jBuffer = jniEnv->CallObjectMethod(m_javaObject->getJObject(), methodObj->getJMethodID(), jData, (jint)dataLength);
    if (jBuffer) jniEnv->DeleteLocalRef(jBuffer);
    jniEnv->DeleteLocalRef(jData);
}
Run Code Online (Sandbox Code Playgroud)