Дженерики Java и JNI - PullRequest
       12

Дженерики Java и JNI

6 голосов
/ 09 февраля 2010

Можно ли вызвать собственную функцию CPP, используя JNI, который принимает общие аргументы? Примерно так:

public static native <T, U, V> T foo(U u, V v);

А затем назовите это как:

//class Foo, class Bar, class Baz are already defined;
Foo f = foo(new Bar(), new Baz());

Может ли кто-нибудь предоставить мне пример, который фактически делает это, или какой-то учебник в сети, который это делает? Я спрашиваю, потому что в моей функции CPN JNI (вызываемой JVM) я получаю неудовлетворенную ошибку ссылки.

Код CPP следует:

JNIEXPORT jobject JNICALL Java_Processor_process (JNIEnv *env, jclass processor_class, jobject obj1, jobject obj2)
{
    jclass bar_class = env->FindClass("Bar");
    jmethodID getFooMethod = env->GetMethodID(bar_class, "getFoo", "()Ljava/lang/Object;");
//getFoo() is defined as `public Foo getFoo();` in Bar.java
    return env->CallObjectMethod(obj1, getFooMethod);
}

EDIT:

Я пытался изменить код, но теперь я получаю NoSuchMethodError:

Java-код:

public static native <U, V> String foo(U u, V v);
//...
String str = foo(new Bar(), new Baz());

Код CPP:

JNIEXPORT jstring JNICALL Java_Processor_process (JNIEnv *env, jclass processor_class, jobject obj1, jobject obj2)
{
    jclass bar_class = env->FindClass("Bar");
    jmethodID getFooMethod = env->GetMethodID(bar_class, "getFoo", "()Ljava/lang/String;");
    //getFoo() is now defined as `public String getFoo();` in Bar.java
    return env->CallObjectMethod(obj1, getFooMethod);
}

Значит ли это, что JNI не поддерживает дженерики или я что-то упустил?

Ответы [ 2 ]

8 голосов
/ 15 февраля 2010

В общем, вы всегда должны использовать javap -s для получения сигнатур методов, которые вы будете искать в JNI. Не угадай.

8 голосов
/ 09 февраля 2010

Существует множество вопросов относительно стирания типов при переполнении стека (например, Получить универсальный тип java.util.List ), что вы ищете, что невозможно сделать ни с JNI, ни с самой Java. Сигнатура типа среды выполнения foo (в обоих мирах или фактически существует только один мир) Object foo(Object u, Object v), которая будет выполнять неявное приведение класса к возвращаемому значению любого типа, с которым вы его вызываете.

Как вы могли заметить (и как уже упоминалось в комментарии к вашему вопросу), у вас нет возможности узнать, что типа T.

EDIT
Кстати, метод getFoo должен возвращать 'Foo', поэтому не стоит делать

jmethodID getFooMethod = env->GetMethodID(bar_class, "getFoo", "()LFoo;");

Если подумать, вся ваша последовательность вызовов кажется неуместной ... у вас есть foo, которая является нативной, возвращающей строкой. Теперь foo ищет getFoo в Bar, который возвращает 'Foo' и возвращает результат этого вызова напрямую, фактически пытаясь вернуть Foo (Foo getFoo() в соответствии с комментарием), где ожидается строка .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...