JNI - Преобразование задания, представляющего Базовые объекты Java (Boolean), в нативные базовые типы (bool) - PullRequest
5 голосов
/ 23 июня 2011

Я думаю, что мне удалось вписать большую часть вопроса в заголовок на этом!

Я извлекаю объект из Java в своем родном коде C ++:

jobject valueObject = env->CallObjectMethod(hashMapObject, hashMapGetMID, keyObject);

Для меня возможно проверить, является ли возвращаемый объект одним из нативных типов, используя что-то вроде:

jclass boolClass = env->FindClass("java/lang/Boolean");
if(env->IsInstanceOf(valueObject, boolClass) == JNI_TRUE) { }

Итак, теперь у меня есть объект задания, который, как я знаю, является логическим (обратите внимание на верхний регистр B)- Вопрос в том, что является наиболее эффективным способом (учитывая, что у меня уже есть объект задания в моем родном коде), чтобы преобразовать это в bool.Типизация не работает, что имеет смысл.

Хотя приведенный выше пример является логическим, я также хочу преобразовать Character-> char, Short-> short, Integer-> int, Float-> float, Double->double.

(Как только я это осуществлю, я опубликую ответ на него, который выполняет Boolean.booleanValue ())

Ответы [ 3 ]

5 голосов
/ 01 июля 2011

У вас есть два варианта.

Вариант # 1 - это то, что вы написали в своем ответе: используйте открытый метод, определенный для каждого класса, для извлечения примитивного значения.

Вариант № 2 более быстрый, но не строго законный: прямой доступ к внутреннему полю. Для логического значения это будет Boolean.value. Для каждого класса примитивного ящика у вас есть fieldID для поля «value», и вы просто читаете поле напрямую. (JNI с радостью игнорирует тот факт, что он объявлен закрытым. Вы также можете писать в «конечные» поля и делать другие вещи, попадающие в категорию «действительно плохих идей».)

Имя поля «значение» вряд ли изменится, так как это нарушит сериализацию. Так что официально это не рекомендуется, но на практике вы можете сойти с рук, если вам нужно.

В любом случае, вы должны кэшировать значения jmethodID / jfieldID, а не искать их каждый раз (поиск относительно дорогой).

Вы также можете использовать менее дорогую функцию IsSameObject, а не IsInstanceof, потому что классы бокса являются "окончательными". Для этого требуется сделать дополнительный вызов GetObjectClass, чтобы получить класс valueObject, но вам нужно сделать это только один раз перед различными сравнениями.

Кстати, будьте осторожны с использованием "char". В приведенном выше примере вы приводите результат CallCharMethod (16-битное значение UTF-16) к типу char (8-битное значение). Помните, что char! = Jchar (если вы не настроили широкие символы), long! = Jlong (если вы не компилируете с 64-битными long).

1 голос
/ 23 июня 2011

Это решение, которое я собираюсь использовать, если не получу больше информации. Надеюсь, это не так сложно, но, зная JNI, я думаю, что это может быть:

    if     (env->IsInstanceOf(valueObject, boolClass)           == JNI_TRUE)
    {
        jmethodID booleanValueMID   = env->GetMethodID(boolClass, "booleanValue", "()Z");
        bool booleanValue           = (bool) env->CallBooleanMethod(valueObject, booleanValueMID);
        addBoolean(key, booleanValue);
    }
    else if(env->IsInstanceOf(valueObject, charClass)           == JNI_TRUE)
    {
        jmethodID characterValueMID  = env->GetMethodID(charClass, "charValue", "()C");
        char characterValue          = (char) env->CallCharMethod(valueObject, characterValueMID);
        addChar   (key, characterValue);
    }
0 голосов
/ 27 июня 2011

В общем, я пишу jni для лучшей производительности. Как получить лучшую производительность? Использование asm, примитивных типов и несколько вызовов методов. Я полагаю, что дизайн вашего возвращаемого метода можно использовать в c / c ++, например: jint, jlong, jboolean, jbyte, jchar и т. д.

Избыточный вызов и преобразование функции приведут к неэффективной и неуправляемой реализации.

...