首页 > 解决方案 > Android:从 C++ 调用带有 byte[] 参数的 java 方法

问题描述

我是一名 Android 开发人员,对 JNI 很陌生——我想做的是将一个字节数组从 c++ 方法传递给 java 方法。这是我的 C++ 方法的样子:

void func(char* bytes) 
{
    jclass callbackClass = fJNIEnv->GetObjectClass(fJObject);
    jmethodID javaFunc = fJNIEnv->GetMethodID(callbackClass, "javaFunc", "([B)V");

    jbyteArray array = fJNIEnv->NewByteArray(sizeof(bytes));
    fJNIEnv->SetByteArrayRegion(array, 0, sizeof(bytes), (jbyte *) bytes);

    fJNIEnv->CallNonvirtualVoidMethod(fJObject, callbackClass, javaFunc, array);
}

这是 javaFunc 方法:

public void javaFunc(byte[] bytes) {
    ...
}

当我调试 func 方法时,bytes它指向一个字符数组,但是当我到达该javaFunc方法时,bytes它类似于 {16, 0, 0, 0} - 它与它所必须的完全不同。任何帮助,将不胜感激。

标签: javaandroidc++arraysjava-native-interface

解决方案


使用sizeof(bytes)是错误的。这为您提供了char*指针本身的字节大小(32 位为 4,64 位为 8),而不是指向的数据的字节大小。

您需要更改func()以传入char数组中的 s 数量。然后,您可以在分配和填充 JNI 数组时使用该数字。

此外,您需要在CallNonvirtualVoidMethod()退出后释放 JNI 数组。

尝试这个:

void func(char* bytes, int numBytes)
{
    jclass callbackClass = fJNIEnv->GetObjectClass(fJObject);
    jmethodID javaFunc = fJNIEnv->GetMethodID(callbackClass, "javaFunc", "([B)V");

    jbyteArray array = fJNIEnv->NewByteArray(numBytes);
    fJNIEnv->SetByteArrayRegion(array, 0, numBytes, (jbyte *) bytes);

    fJNIEnv->CallNonvirtualVoidMethod(fJObject, callbackClass, javaFunc, array);
    fJNIEnv->DeleteLocalRef(array);
}

或者,传入更合适的 C++ 容器,例如std::vector<char>

void func(const std::vector<char> &bytes)
{
    jclass callbackClass = fJNIEnv->GetObjectClass(fJObject);
    jmethodID javaFunc = fJNIEnv->GetMethodID(callbackClass, "javaFunc", "([B)V");

    jbyteArray array = fJNIEnv->NewByteArray(bytes.size());
    fJNIEnv->SetByteArrayRegion(array, 0, bytes.size(), (jbyte *) bytes.data());

    fJNIEnv->CallNonvirtualVoidMethod(fJObject, callbackClass, javaFunc, array);
    fJNIEnv->DeleteLocalRef(array);
}

推荐阅读