2

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.

2
  • 3
    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 the number of chars in the array, ie void func(char* bytes, int numBytes), or pass in a more appropriate container, like std::vector<char>, ie func(const std::vector<char> &bytes). Then, you can use the real byte count when allocating and filling the JNI array Commented Aug 21, 2018 at 20:40
  • 1
    Also, you need to free the JNI array after CallNonvirtualVoidMethod() exits, ie fJNIEnv->DeleteLocalRef(array);. Commented Aug 21, 2018 at 20:45

2 Answers 2

2

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 chars 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);
}
Sign up to request clarification or add additional context in comments.

Comments

2

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

1 Comment

Don't forget to pass the number of bytes to fJNIEnv->NewByteArray() as well, as using sizeof(bytes) is wrong there, too

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.