今天说一下在jni开发中常另新手迷惑的JNIEnv这个东西
比如一个c语言的函数
JNIEXPORT jstring JNICALL Java_com_mmmmar_nativethread_MainActivity_native(JNIEnv *env, jobject obj){ (*env)->newStringUTF("hello"); }
在这里为什么要用 (*env)->呢? 难道JNIEnv这个类型也是一个指针?
而在c++中却可以直接
JNIEXPORT jstring JNICALL Java_com_mmmmar_nativethread_MainActivity_native(JNIEnv *env, jobject obj){ env->newStringUTF("hello"); }
这是怎么做到的呢?
我们来看一下jni.h中的一些定义
typedef _JNIEnv JNIEnv; struct JNINativeInterface { void* reserved0; void* reserved1; void* reserved2; void* reserved3; jint (*GetVersion)(JNIEnv *); jclass (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*, jsize); jclass (*FindClass)(JNIEnv*, const char*); .....等等一系列函数 } struct _JNIEnv { /* do not rename this; it does not seem to be entirely opaque */ const struct JNINativeInterface* functions; #if defined(__cplusplus) jint GetVersion() { return functions->GetVersion(this); } jclass DefineClass(const char *name, jobject loader, const jbyte* buf, jsize bufLen) { return functions->DefineClass(this, name, loader, buf, bufLen); } jclass FindClass(const char* name) { return functions->FindClass(this, name); } ......等等一系列函数 #endif /*__cplusplus*/ };
我们需要关注的大致就是上边那些,其实把需要这些拿出来一看就很清楚了。
首先 typedef _JNIEnv JNIEnv 这个JNIEnv类型其实是_JNIEnv类型 ,而_JniEnv是一个结构体。
先看里边的第一项 const struct JNINativeInterface* functions 一个结构体的指针,在这个结果体里保存了Jni函数的地址,当我们需要调用jni函数时在最终会在这里找到函数的入口。
看到这里就可以明白(*env)->是什么意思了吧,它实际就等效于 (*env).functions-> 因为functions是结构的第一项,结构体指针的地址就是functions这个指针的地址。
再说在c++中的 env-> 问题,可以看到在_JNIEnv里有一个宏定义#if defined(__cplusplus) 在c++中,struct 实际是一个类,而那些jni函数被包装了一层,成为了_JNIEnv的成员函数
希望可以帮到一些刚接触jni的人,至少我刚接触时对这地方很困惑