日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

【Android NDK 开发】JNI 方法解析 ( JNIEnv *env 参数 )

發布時間:2025/6/17 Android 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android NDK 开发】JNI 方法解析 ( JNIEnv *env 参数 ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一、 JNI 方法解析
  • 二、 JNIEnv *env 參數解析
  • 三、 C 語言 環境中 JNIEnv *env 參數解析
  • 四、 C ++ 環境中 JNIEnv *env 參數解析



總結 : JNI 中定義的函數指針 , 實際都定義在 JNINativeInterface 結構體中 ;

C 語言中的 JNIEnv * env 實際上是 JNINativeInterface ** 類型 , 調用其中的方法指針時 , 先解引用 , 得到其一維指針 , 然后調用對用函數指針 (* env)->函數指針 ;

C++ 中專門定義了 JNIEnv 結構體類型 , 其中的函數直接封裝調用了 JNINativeInterface 結構體中的函數指針 , 只需要調用 JNIEnv 結構體中的方法即可 , C++ 中的 JNIEnv * env , 可以直接調用其中的方法 , 將其當做一個對象使用 , env->方法名稱 , 即可完成調用 ;



一、 JNI 方法解析



1 . JNI 方法定義 :


① 在 Android 的 Java 層定義方法 : 在 MainActivity 類中定義 如下 Native 方法 ;

public native String stringFromJNI();

② Native 方法實現 : 下面是一個 Native 方法實現的示例 ;

extern "C" JNIEXPORT jstring JNICALL Java_kim_hsl_jni_MainActivity_stringFromJNI(JNIEnv *env,jobject /* this */) {// 創建 C++ 字符串std::string hello = "Hello from C++";// 返回 jstring 類型的字符串return env->NewStringUTF(hello.c_str()); }

2 . 分析上述 JNI 方法 :


① extern “C” : 表示 C 語言 和 C++ 的兼容 ;

② JNIEXPORT jstring JNICALL : 這是兩個宏定義 , 在 Linux 和 Windows 中分別有不同的表示 ; 其中的 jstring 表示返回值類型是 Java 中的 String 類型 ;


關于 JNIEXPORT 與 JNICALL 宏定義 , 參考下面的博客 :
【Android NDK 開發】JNIEXPORT 與 JNICALL 宏定義作用


③ JNIEnv *env : 其中第一個參數 JNIEnv *env 代表了 JNI 環境 ;


④ jobject 參數 : 該 Native 方法定義在 MainActivity 類中 ;


  • 1> 非靜態方法 : 如果該方法是非靜態方法 , 那么 jobject 參數表示 MainActivity 類的對象 ;

  • 2> 靜態方法 : 如果該方法是靜態方法 , 那么 jobject 參數表示 MainActivity.class ( Class 對象 ) ;



二、 JNIEnv *env 參數解析



在 C 語言 和 C++ 中 , JNIEnv 代表著不同的含義 ;


1 . JNIEnv 類型聲明 :

#if defined(__cplusplus) typedef _JNIEnv JNIEnv; typedef _JavaVM JavaVM; #else typedef const struct JNINativeInterface* JNIEnv; typedef const struct JNIInvokeInterface* JavaVM; #endif

由上面的代碼可知 , JNIEnv 是通過 typedef 將其它的類型定義為 JNIEnv 類型的 ;

__cplusplus 是 C++ 編譯器中定義的宏 , C 語言編譯器中沒有定義該宏 , 通過該宏定義 , 可以區分當前是 C++ 環境還是 C語言環境 ;

#if defined(__cplusplus) 分支中聲明的是 C++ 環境下的 JNIEnv 類型 ;

#else 分支中聲明的是 C 語言環境下的 JNIEnv 類型 ;


2 . 兩種 typedef 聲明別名的含義


① C 語言別名 : C 語言中 將 JNINativeInterface 結構體指針 類型 聲明為 JNIEnv 類型 ;

typedef const struct JNINativeInterface* JNIEnv;

② C ++ 別名 : C ++ 中 , 將 _JNIEnv 結構體類型聲明為 JNIEnv 類型 ;

typedef _JNIEnv JNIEnv;

三、 C 語言 環境中 JNIEnv *env 參數解析



1 . JNIEnv 類型 : C 語言環境中 , 系統將 JNINativeInterface* 類型 聲明為 JNIEnv 別名 ;


2 . JNINativeInterface 結構體 : JNINativeInterface 是結構體類型 , 其中定義了 229 個函數指針 , 用于處理 Java 層 與 Native 層的數據交互信息 ;


3 . C 語言環境中 , 調用 JNINativeInterface 結構體中的函數指針 :


① 類型轉換 : 給定的參數是 JNIEnv *env 類型的 , 即 JNINativeInterface ** env 類型 , 是一個 JNINativeInterface 結構體邊來那個的二級指針 ;

② 通過 JNINativeInterface 指針調用 ( 推薦) : 首先要 解引用 ( *env ) , 該變量就變成了 JNINativeInterface 結構體變量的 一級指針 , 使用 -> 即可調用指定方法 , ( *env ) -> NewStringUTF( “Hello World !” );

③ 通過 JNINativeInterface 結構體調用 ( 不常用 ) : ( **env ).NewStringUTF( “Hello World !” ) , 相當于將上面的 -> 操作符變成 * . 操作符 ;


4 . JNINativeInterface 結構體部分代碼示例 : 該結構體定義在 jni.h 頭文件中 ;

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*);jmethodID (*FromReflectedMethod)(JNIEnv*, jobject);jfieldID (*FromReflectedField)(JNIEnv*, jobject);/* spec doesn't show jboolean parameter */jobject (*ToReflectedMethod)(JNIEnv*, jclass, jmethodID, jboolean);jclass (*GetSuperclass)(JNIEnv*, jclass);jboolean (*IsAssignableFrom)(JNIEnv*, jclass, jclass);/* spec doesn't show jboolean parameter */jobject (*ToReflectedField)(JNIEnv*, jclass, jfieldID, jboolean);jint (*Throw)(JNIEnv*, jthrowable);jint (*ThrowNew)(JNIEnv *, jclass, const char *);jthrowable (*ExceptionOccurred)(JNIEnv*);void (*ExceptionDescribe)(JNIEnv*);void (*ExceptionClear)(JNIEnv*);void (*FatalError)(JNIEnv*, const char*);...jstring (*NewStringUTF)(JNIEnv*, const char*);... };

JNINativeInterface 是結構體類型 , 其中定義了 229 個函數指針 , 用于處理 Java 層 與 Native 層的數據交互信息



四、 C ++ 環境中 JNIEnv *env 參數解析



1 . C++ 環境中 _JNIEnv 類型 : 在 C++ 中 , 將 _JNIEnv 結構體類型 通過 typedef 為其聲明別名 JNIEnv ;


2 . _JNIEnv 結構體 : 該結構體中封裝了一個 JNINativeInterface 結構體類型指針 , _JNIEnv 結構體中也封裝了 229 個 方法 , 每個方法都調用 對應的 JNINativeInterface* functions 中的函數指針 ;


3 . C ++ 語言環境中 , 調用 _JNIEnv 結構體中的函數 :


① 類型轉換 : 給定的參數是 JNIEnv *env 類型的 , 即 _JNIEnv * env 類型 ;

② 通過 _JNIEnv 指針調用 ( 推薦) : 直接使用 -> 符號訪問該方法即可 , env-> NewStringUTF( “Hello World !” );


_JNIEnv 結構體 部分代碼示例 :

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); }jmethodID FromReflectedMethod(jobject method){ return functions->FromReflectedMethod(this, method); }jfieldID FromReflectedField(jobject field){ return functions->FromReflectedField(this, field); }jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic){ return functions->ToReflectedMethod(this, cls, methodID, isStatic); }jclass GetSuperclass(jclass clazz){ return functions->GetSuperclass(this, clazz); }...jstring NewStringUTF(const char* bytes){ return functions->NewStringUTF(this, bytes); }... } 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的【Android NDK 开发】JNI 方法解析 ( JNIEnv *env 参数 )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。