JNIJava包装器:如何传递byte[]参数 我需要用JNI调用C++的java API。我正在尝试传递一个字节*,如下所示:
JavaJNIJava包装器:如何传递byte[]参数 我需要用JNI调用C++的java API。我正在尝试传递一个字节*,如下所示:,java,c++,java-native-interface,Java,C++,Java Native Interface,Java void OperateData(字节[]数据,int数据长度) { //一些实现 } C++ void OperateData(字节*数据,int数据长度) { JavaMethod*methodObj=getMethod(_T(“OperateData”); JNIEnv*JNIEnv=JvmManager::GetInstance()->GetJNIEnv(); jobject jBuffer=jniEnv->CallObjectMethod(m_javaObject->get
void OperateData(字节[]数据,int数据长度)
{
//一些实现
}
C++
void OperateData(字节*数据,int数据长度)
{
JavaMethod*methodObj=getMethod(_T(“OperateData”);
JNIEnv*JNIEnv=JvmManager::GetInstance()->GetJNIEnv();
jobject jBuffer=jniEnv->CallObjectMethod(m_javaObject->getJObject(),methodObj->getJMethodID(),(jobject)数据,(jint)数据长度);
}
这是行不通的。它抛出了一个异常。你能告诉我我做错了什么吗
<强>更新< /强>:我根据建议修改C++代码如下。我还是有同样的问题。还有什么不对劲吗
void OperateData(字节*数据,int数据长度)
{
JavaMethod*methodObj=getMethod(_T(“OperateData”);
JNIEnv*JNIEnv=JvmManager::GetInstance()->GetJNIEnv();
jbyteArray jBuff=jniEnv->NewByteArray(数据长度);
jniEnv->SetByteArrayRegion(jBuff,0,dataLength,(jbyte*)数据);
jobject jBuffer=jniEnv->CallObjectMethod(m_javaObject->getJObject(),methodObj->getJMethodID(),jBuff,(jint)数据长度);
jniEnv->ReleaseByteArrayElements(jBuff,(jbyte*)数据,0);
}
所有这些都毫无意义
javap-s
的输出所示。因此Java方法的JNI签名肯定不仅仅是“OperateData”
李>
methodObj
必须为null,或者包含一个为零的jmethodID
,仅此一点就足以解释您的问题void
,因此它不会返回jobject
void
,因此您应该使用ReleaseByteArrayElements()
不正确。在这里您根本不需要调用它,但是当您调用它时,它会被通过getbytearrayellements()
获得的指针调用。不是用你自己的数据您不能简单地将原始C/C++
byte*
指针类型转换为表示Java字节数组的jobject
。您需要:
- 通过在JVM内存中分配一个新的Java字节数组
- 然后通过以下任一方式将原始字节复制到该Java数组的内存中:
- ,
,以及memcpy()
- ,
- 然后将该Java数组传递给目标Java方法
- 最后通过发布Java数组
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);
}
更新:在评论中,您说您将Java代码更改为返回一个字节[]
,而不是无效
。如果是这样,你需要相应地调整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);
}
如果您看到一个异常,您将希望发布完整的stacktrace和您的问题,它将提交为catch处理的未知异常(…)根据您的建议修改JNI,如下所示: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*)数据);jobject jBuffer=JNIEnv->CallObjectMethod(m_javaObject->->getJObject(),methodObj->getjmethododid(),jBuff,(jint)dataLength);}@LokanathNayak关闭。您没有进行错误处理,并且在完成时没有释放Java数组
JObject
应该是JObject
。请参见编辑历史记录。这是我唯一编辑的东西,现在不在那里了。@EJP您在我自己编辑的时候做了编辑。你的编辑丢失了。我重新应用了它没问题,我知道它是怎么发生的。
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);
}