Javagenerics和JNI
是否可以使用带有generics参数的JNI调用本机CPP函数? 类似于以下内容:
public static native 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 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不支持generics,或者我错过了什么?
关于堆栈溢出的类型擦除有很多问题(例如, 获取generics类型的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
在Bar
查找getFoo
,它返回’Foo’,并直接返回该调用的结果,有效地尝试返回一个Foo
(根据注释的Foo getFoo()
),其中字符串是预期的。
通常,您应该始终使用javap -s来获取您将要在JNI中查找的方法的签名。 不要猜。