是否可以使用带有泛型参数的JNI调用本机CPP函数?如下所示:
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());
任何人都可以请我提供一个实际上正在进行此操作的示例或网上的一些教程吗?我问,因为在我的CPP 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);
}
修改
我试过修改代码,但现在我得到了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不支持泛型,或者我错过了什么?
答案 0 :(得分:8)
关于堆栈溢出的类型擦除有很多问题(例如Get generic type of java.util.List),你要做的事情是JNI和Java本身都不可能。 foo的运行时类型签名是(在两个世界中,或实际上,只有一个世界)Object foo(Object u, Object v)
,它将对返回值执行隐式类强制转换为您调用它的任何类型。
正如您可能会注意到的(正如您对问题的评论所述),您无法知道T
的类型。
修改的:
顺便说一句,getFoo方法应该返回'Foo',所以你不应该做
jmethodID getFooMethod = env->GetMethodID(bar_class, "getFoo", "()LFoo;");
想想看,你的整个通话序列似乎不合适......你有一个本地的foo
,返回字符串。现在foo
在getFoo
中查找Bar
,返回'Foo',并直接返回该调用的结果,有效地尝试返回Foo
({{1}根据评论)预期字符串。
答案 1 :(得分:8)
通常,您应该始终使用javap -s来获取您将要在JNI中查找的方法的签名。不要猜。