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)
您不能简单地将原始 C/C++byte*指针类型转换为jobject表示 Java 字节数组的类型。您需要使用 JNI 函数来:
在 JVM 的内存中分配一个新的 Java 字节数组,通过NewByteArray().
然后通过以下任一方式将原始字节复制到该 Java 数组的内存中:
然后将该 Java 数组传递给您的目标 Java 方法。
然后最终通过DeleteLocalRef().
例如:
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)