在访问JNI接口时,为什么C需要额外的间接层,而C ++却没有?

时间:2013-01-17 22:50:24

标签: java c++ c java-native-interface

在用于通过“C”访问的代码sample中,env指针的使用方式如下:

const char *str = (*env)->GetStringUTFChars(env, s, 0);

对于C ++,sample进行相同的调用:

const char *str = env->GetStringUTFChars(s, 0); 

该文件继续说:

  

使用C ++,额外的间接级别和接口指针参数从源代码中消失。但是,底层机制与C完全相同。在C ++中,JNI函数被定义为内联成员函数,扩展为它们的C对应函数。

该语句是否意味着C ++版本最终将扩展到C版本并具有相同的间接级别?

我没有查看头文件,但我很困惑。有人可以解释这种差异吗?

3 个答案:

答案 0 :(得分:4)

问题中引用的解释解释了这一点。 C ++支持内联成员函数,但C不支持。 JNIEnv的C ++定义包括C定义不包含的函数定义。 C ++定义如下所示:

char const* JNIEnv::GetStringUTFChars(jstring s, jint i)
{
  return (*this)->GetStringUTFChars(this, s, i);
}

C版本中调用的函数实际上是一个函数指针。本质上,JNIEnv*是一个vptr,指向带有一堆JNI提供的函数指针的结构。为方便起见,C ++直接在JNIEnv中提供了其他定义,以避免重复函数调用的this参数。

答案 1 :(得分:3)

我还没有确切地检查过它们是如何实现的,但我非常有信心它是这样的:

  • 在C ++中,JNIEnv *将是方法的“this”,这使得方法也可以使用env指针
  • 在C中,函数(结构中的函数指针指向)的唯一方法是使用它,如果有人将它作为参数传递。

答案 2 :(得分:1)

所以,看看OpenJDK source,jni.h在标题中有这个:

770 /*
771  * We use inlined functions for C++ so that programmers can write:
772  *
773  *    env->FindClass("java/lang/String")
774  *
775  * in C++ rather than:
776  *
777  *    (*env)->FindClass(env, "java/lang/String")
778  *
779  * in C.
780  */
781 
782 struct JNIEnv_ {
783     const struct JNINativeInterface_ *functions;
784 #ifdef __cplusplus
785 
786     jint GetVersion() {
787         return functions->GetVersion(this);
788     }

感谢大家澄清这一点。