Как мне вызвать String.getBytes () в JNI?Я хочу получить байтовый массив в JNI, но CallByteMethod просто возвращает jbyte, а не jbytearray - PullRequest
0 голосов
/ 29 января 2019

Я пытаюсь вызвать String.getBytes() метод для получения байтового массива в JNI из строкового объекта.JNI имеет методы CallByteMethod, CallByteMethodV и CallByteMethodA, которые возвращают jbyte, но у него нет методов для возврата байтового массива java.

Я попытался вызвать метод CallByteMethod, но я получаю ошибку

JNI ОБНАРУЖИЛА ОШИБКУ В ПРИЛОЖЕНИИ: использование удаленной локальной ссылки 0xd5ec7fe1

Другой код, который я пробовал, использовал приведение jbytearray, подобное этому

jbyteArray keyBytes = (jbyteArray)(*env)->CallByteMethod(env, stringValue, getBytesMId);

, так как в IDE появилось предупреждение

Получение указателя из целого числа без приведения.

, но затем я получаю другую ошибку, которая говорит

JNI ОБНАРУЖЕНО ОШИБКА В ПРИЛОЖЕНИИ: возвращаемый тип CallByteMethod не соответствует байту [] java.lang.String.getBytes ()

Ниже мой код:

JNIEXPORT jstring JNICALL
Java_net_jni_test_MainActivity_callTest(JNIEnv *env, jobject instance) {

    jstring stringValue = "test";

    jclass stringClass = (*env)->FindClass(env, "java/lang/String");
    jmethodID getBytesMId = (*env)->GetMethodID(env, stringClass, "getBytes", "()[B");

    jbyteArray keyBytes = (*env)->CallByteMethod(env, stringValue, getBytesMId);

    return (*env)->NewStringUTF(env, "1111");
}

1 Ответ

0 голосов
/ 29 января 2019

Просто отметьте некоторые ошибки в вашем коде:

  1. Ниже неправильная строка:

    jstring stringValue = "test";
    

    И это должно быть так:

    jstring stringValue = (*env)->NewStringUTF(env, "test");
    
  2. Используйте CallObjectMethod, чтобы получить jbyteArray, не забудьте привести тип возвращаемого значения к jbyteArray.См. Ниже:

    jbyteArray keyBytes = (jbyteArray)(*env)->CallObjectMethod(env, stringValue, getBytesMId);
    
  3. Ниже приведен скриншот с ожидаемым результатом.

    enter image description here

Для полного источника:

JNIEXPORT jstring JNICALL
Java_net_jni_test_MainActivity_callTest(JNIEnv *env, jobject instance) {
    jstring stringValue = (*env)->NewStringUTF(env, "test");

    jclass stringClass = (*env)->FindClass(env, "java/lang/String");
    jmethodID getBytesMId = (*env)->GetMethodID(env, stringClass, "getBytes", "()[B");

    jbyteArray keyBytes = (jbyteArray)(*env)->CallObjectMethod(env, stringValue, getBytesMId);

    // determine the needed length and allocate a buffer for it
    jsize num_bytes = (*env)->GetArrayLength(env, keyBytes);


    // obtain the array elements
    jbyte* elements = (*env)->GetByteArrayElements(env, keyBytes, NULL);
    if (!elements) {
        // handle JNI error ...
    }

    for(int i = 0; i < num_bytes; i++) {
        char ch = elements[i];
        ALOGI("arrayLength: %c", ch);
    }

    // Do not forget to release the element array provided by JNI:
    (*env)->ReleaseByteArrayElements(env, keyBytes, elements, JNI_ABORT);
}

Обратите внимание на разницу в C ++ JNIи C JNI.Например, JNI в стиле C имеет следующие соглашения:

jmethodID getBytesMId = (*env)->GetMethodID(env, stringClass, "getBytes", "()[B");

Но C ++ похож на:

jmethodID getBytesMId = env->GetMethodID(stringClass, "getBytes", "()[B");
...