简体   繁体   中英

Android: Calling java method with byte[] parameter from c++

I am an Android developer and new to JNI thing - what I'm trying to do is pass a byte array from c++ method to java method. Here is what my c++ method looks like:

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);
}

and here is the javaFunc method:

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

when I'm debugging the func method, bytes is pointing to an array of chars, but when I get to the javaFunc method, bytes is something like {16, 0, 0, 0} - it's nothing like what it has to be. Any help would be appreciated.

You'r SetByteArrayRegion call is wrong.

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

it should be

fJNIEnv->SetByteArrayRegion(fJNIEnv, array, 0, number of bytes, (jbyte *) bytes);

Syntax is:

SetByteArrayRegion(env, byteArray, from, size, a + from);

Using sizeof(bytes) is wrong. That gives you the byte size of the char* pointer itself (4 in 32bit, 8 in 64bit), NOT the byte size of the data that is being pointed to.

You need to change func() to pass in the number of char s in the array. Then, you can use that number when allocating and filling the JNI array.

Also, you need to free the JNI array after CallNonvirtualVoidMethod() exits.

Try this:

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);
}

Alternatively, pass in a more appropriate C++ container, like 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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM